作者:Mohsin Nasir 與 smandia
Note
這不是這篇文章的最新版本。 關於目前版本,請參閱 本文的 .NET 10 版本。
Warning
不再支援此版本的 ASP.NET Core。 如需詳細資訊,請參閱 .NET 和 .NET Core 支持原則。 如需目前的版本,請參閱 本文的 .NET 9 版本。
分散式快取是由多個應用程式伺服器共用的快取,通常作為外部服務 (相對於對快取進行存取的應用程式伺服器) 進行維護。 分散式快取可以改善 ASP.NET Core 應用程式的效能和可擴縮性,尤其是當應用程式是由雲端服務或伺服器陣列裝載時。
分散式快取相比其他快取案例有幾項優點:快取資料會儲存在個別的應用程式伺服器上。
當快取資料散發時,資料具備如下特徵:
- 在多個伺服器的要求之間具備一致性。
- 在伺服器重新啟動和應用程式部署後仍然存續。
- 不使用本機記憶體。
分散式快取組態是特定與實作。 本文說明如何設定 SQL Server、Redis 或 Postgres 分散式快取。 第三方實作也可供使用,例如 NCache (GitHub 上的 NCache)、Cosmos DB 和 Postgres。 無論選取哪一個實作,應用程式都會使用 IDistributedCache 介面與快取互動。
檢視或下載範例程式碼 \(英文\) (如何下載)
Warning
本文使用本機資料庫,其不需要使用者進行驗證。 實際執行應用程式應該使用可用的最安全驗證流程。 如需已部署測試與實際執行應用程式驗證的詳細資訊,請參閱安全驗證流程。
Prerequisites
為使用的分散式快取提供者新增套件參考:
- 針對 Redis 分散式快取,Microsoft.Extensions.Caching.StackExchangeRedis。
- 針對 SQL Server,Microsoft.Extensions.Caching.SqlServer。
- 針對 Postgres,使用 Microsoft.Extensions.Caching.Postgres。
- 適用於 Cosmos DB 的 Microsoft.Extensions.Caching.Cosmos。
- 針對 NCache 分散式快取,NCache.Microsoft.Extensions.Caching.OpenSource。
IDistributedCache 介面
IDistributedCache 介面提供下列方法來操作分散式快取實作中的項目:
-
Get、GetAsync:接受字串索引鍵,並在快取中找到時擷取快取項目做為
byte[]陣列。 -
Set、SetAsync:使用字串索引鍵將項目 (作為
byte[]陣列) 新增至快取。 - Refresh、RefreshAsync:根據快取索引鍵重新整理快取中的項目,重設滑動期限逾時 (如有)。
- Remove、RemoveAsync:移除快取項目 (根據其字串索引鍵)。
建立分散式快取服務
在 IDistributedCache 中註冊 Program.cs 實作。 本主題中所述了下列由架構提供的實作:
分散式 Redis 快取
我們建議生產應用程式使用分散式 Redis 快取,因為它是效能最高的應用程式。 如需詳細資訊,請參閱建議。
Redis 是一種開放原始碼的記憶體內部資料存放區,通常用來作為分散式快取。 您可以為 Azure 裝載的 ASP.NET Core 應用程式設定 Azure Cache for Redis,並可使用 Azure Cache for Redis 進行本機開發。
應用程式會藉由呼叫 RedisCache,使用 AddStackExchangeRedisCache 執行個體來設定快取實作。 針對輸出快取,請使用 AddStackExchangeRedisOutputCache。
- 建立 Azure Cache for Redis。
- 將主要連接字串 (StackExchange.Redis) 複製到 Configuration。
- 本機開發:使用秘密管理員儲存連接字串。
- Azure:將連接字串儲存在安全存放區中,例如 Azure Key Vault
下列程式碼會啟用 Azure Cache for Redis:
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = builder.Configuration.GetConnectionString("MyRedisConStr");
options.InstanceName = "SampleInstance";
});
上述程式碼假設主要連接字串 (StackExchange.Redis) 已儲存在組態中,且金鑰名稱為 MyRedisConStr。
如需詳細資訊,請參閱 Azure Cache for Redis。
如需瞭解有關本機 Redis 快取替代方法的討論,請參閱此 GitHub 問題。
分散式記憶體快取
分散式記憶體快取 (AddDistributedMemoryCache) 是架構提供的 IDistributedCache 實作,會將項目儲存在記憶體中。 分散式記憶體快取並非實際的分散式快取。 快取項目會由應用程式執行個體儲存在應用程式執行所在的伺服器上。
分散式記憶體快取是實用的實作:
- 在開發和測試案例中。
- 當單一伺服器用於生產環境而且記憶體耗用量不是問題時。 實作分散式記憶體快取會擷取快取的資料儲存體。 如果需要多個節點或容錯,它可在未來實作真正的分散式快取解決方案。
當應用程式在 Program.cs 的開發環境中執行時,範例應用程式會使用分散式記憶體快取:
builder.Services.AddDistributedMemoryCache();
分散式 SQL Server 快取
分散式 SQL Server 快取實作 (AddDistributedSqlServerCache) 可讓分散式快取使用 SQL Server 資料庫作為其備份存放區。 若要在 SQL Server 執行個體中建立 SQL Server 快取項目資料表,您可以使用 sql-cache 工具。 此工具會使用您指定的名稱和架構來建立資料表。
執行 sql-cache create 命令以在 SQL Server 中建立資料表。 提供 SQL Server 執行個體 (Data Source)、資料庫 (Initial Catalog)、架構 (例如,dbo) 以及資料表名稱 (例如,TestCache):
dotnet sql-cache create "Data Source=(localdb)/MSSQLLocalDB;Initial Catalog=DistCache;Integrated Security=True;" dbo TestCache
系統將記錄訊息,指出工具成功:
Table and index were created successfully.
sql-cache 工具所建立的資料表具有下列架構:
Note
應用程式應該使用 IDistributedCache 的執行個體來操作快取值,而不是 SqlServerCache。
範例應用程式會在 SqlServerCache 中的非開發環境中實作 Program.cs:
builder.Services.AddDistributedSqlServerCache(options =>
{
options.ConnectionString = builder.Configuration.GetConnectionString(
"DistCache_ConnectionString");
options.SchemaName = "dbo";
options.TableName = "TestCache";
});
Note
ConnectionString(選擇性地,SchemaName 和 TableName) 通常儲存在原始檔控制之外 (例如,由秘密管理員儲存,或儲存在 appsettings.json/appsettings.{Environment}.json 檔案中)。 連接字串可能包含應不保留在原始檔控制系統中的認證。
分散式 Postgres 快取
適用於PostgreSQL的 Azure 資料庫 可透過介面作為分散式快取備份存放區 IDistributedCache 。 適用於 PostgreSQL 的 Azure 資料庫是完全受控、AI 就緒的資料庫即服務 (DBaaS) 供應專案,建置在開放原始碼 PostgreSQL 引擎上,其設計目的是支援具有可預測效能、強固安全性、高可用性和無縫延展性的任務關鍵性工作負載。
安裝 Microsoft.Extensions.Caching.Postgres NuGet 套件之後,請設定分散式快取,如下所示:
- 註冊服務
using Microsoft.Extensions.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
// Register Postgres distributed cache
builder.Services.AddDistributedPostgresCache(options => {
options.ConnectionString = builder.Configuration.GetConnectionString("PostgresCache");
options.SchemaName = builder.Configuration.GetValue<string>("PostgresCache:SchemaName", "public");
options.TableName = builder.Configuration.GetValue<string>("PostgresCache:TableName", "cache");
options.CreateIfNotExists = builder.Configuration.GetValue<bool>("PostgresCache:CreateIfNotExists", true);
options.UseWAL = builder.Configuration.GetValue<bool>("PostgresCache:UseWAL", false);
// Optional: Configure expiration settings
var expirationInterval = builder.Configuration.GetValue<string>("PostgresCache:ExpiredItemsDeletionInterval");
if (!string.IsNullOrEmpty(expirationInterval) && TimeSpan.TryParse(expirationInterval, out var interval)) {
options.ExpiredItemsDeletionInterval = interval;
}
var slidingExpiration = builder.Configuration.GetValue<string>("PostgresCache:DefaultSlidingExpiration");
if (!string.IsNullOrEmpty(slidingExpiration) && TimeSpan.TryParse(slidingExpiration, out var sliding)) {
options.DefaultSlidingExpiration = sliding;
}
});
var app = builder.Build();
- 使用快取
public class MyService {
private readonly IDistributedCache _cache;
public MyService(IDistributedCache cache) {
_cache = cache;
}
public async Task<string> GetDataAsync(string key) {
var cachedData = await _cache.GetStringAsync(key);
if (cachedData == null) {
// Fetch data from source
var data = await FetchDataFromSource();
// Cache the data with options
var options = new DistributedCacheEntryOptions {
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30),
SlidingExpiration = TimeSpan.FromMinutes(5)
};
await _cache.SetStringAsync(key, data, options);
return data;
}
return cachedData;
}
}
分散式 NCache 快取
NCache 是 .NET 原生開發的開放原始碼記憶體內部分散式快取。 NCache 可在本機運作,對於在 Azure 或其他裝載平臺上執行的 ASP.NET Core 應用程式,則設定為分散式快取叢集。
若要在本機計算機上安裝和設定 NCache,請參閱 Windows 和 Linux 快速入門指南。
若要設定 NCache:
- 安裝 NCache 開放原始碼 NuGet。
- 在 client.ncconf 中設定快取叢集。
- 將下列程式碼新增至
Program.cs:
builder.Services.AddNCacheDistributedCache(configuration =>
{
configuration.CacheName = "democache";
configuration.EnableLogs = true;
configuration.ExceptionsEnabled = true;
});
分散式 Azure Cosmos DB 快取
Azure Cosmos DB 可藉由使用 IDistributedCache 介面,在 ASP.NET Core 中用來作為工作階段狀態供應器。 Azure Cosmos DB 是完全受控 NoSQL 和關聯式資料庫,適用於新式應用程式開發,可為任務關鍵性應用程式提供資料的高可用性、可擴縮性和低延遲存取。
安裝 Microsoft.Extensions.Caching.Cosmos NuGet 套件之後,設定 Azure Cosmos DB 分散式快取,如下所示:
重複使用現有的用戶端
設定分散式快取最簡單的方式是重複使用現有的 Azure Cosmos DB 用戶端。 在此情況下,當處置提供者時,不會處置 CosmosClient 執行個體。
services.AddCosmosCache((CosmosCacheOptions cacheOptions) =>
{
cacheOptions.ContainerName = Configuration["CosmosCacheContainer"];
cacheOptions.DatabaseName = Configuration["CosmosCacheDatabase"];
cacheOptions.CosmosClient = existingCosmosClient;
cacheOptions.CreateIfNotExists = true;
});
建立新用戶端
或者,具現化新的用戶端。 在此情況下,CosmosClient 執行個體會在處置提供者時處置。
services.AddCosmosCache((CosmosCacheOptions cacheOptions) =>
{
cacheOptions.ContainerName = Configuration["CosmosCacheContainer"];
cacheOptions.DatabaseName = Configuration["CosmosCacheDatabase"];
cacheOptions.ClientBuilder = new CosmosClientBuilder(Configuration["CosmosConnectionString"]);
cacheOptions.CreateIfNotExists = true;
});
使用分散式快取
若要使用 IDistributedCache 介面,請在應用程式中要求 IDistributedCache 的執行個體。 執行個體是由相依性插入 (DI) 提供。
當範例應用程式啟動時,IDistributedCache 會插入至 Program.cs。 目前的時間會使用 IHostApplicationLifetime 快取 (如需詳細資訊,請參閱一般主機:IHostApplicationLifetime):
app.Lifetime.ApplicationStarted.Register(() =>
{
var currentTimeUTC = DateTime.UtcNow.ToString();
byte[] encodedCurrentTimeUTC = System.Text.Encoding.UTF8.GetBytes(currentTimeUTC);
var options = new DistributedCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromSeconds(20));
app.Services.GetService<IDistributedCache>()
.Set("cachedTimeUTC", encodedCurrentTimeUTC, options);
});
範例應用程式會將 IDistributedCache 插入 IndexModel,以供 [索引] 頁面使用。
每次載入索引頁面時,都會檢查快取是否存在 OnGetAsync 中的快取時間。 如果快取的時間尚未過期,則會顯示時間。 如果自上次存取快取時間之後已經過 20 秒 (上次載入此頁面的時間),頁面會顯示 [快取時間過期]。
選取 [重設快取時間] 按鈕可立即將快取的時間更新為目前時間。 此按鈕會觸發 OnPostResetCachedTime 處理常式方法。
public class IndexModel : PageModel
{
private readonly IDistributedCache _cache;
public IndexModel(IDistributedCache cache)
{
_cache = cache;
}
public string? CachedTimeUTC { get; set; }
public string? ASP_Environment { get; set; }
public async Task OnGetAsync()
{
CachedTimeUTC = "Cached Time Expired";
var encodedCachedTimeUTC = await _cache.GetAsync("cachedTimeUTC");
if (encodedCachedTimeUTC != null)
{
CachedTimeUTC = Encoding.UTF8.GetString(encodedCachedTimeUTC);
}
ASP_Environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
if (String.IsNullOrEmpty(ASP_Environment))
{
ASP_Environment = "Null, so Production";
}
}
public async Task<IActionResult> OnPostResetCachedTime()
{
var currentTimeUTC = DateTime.UtcNow.ToString();
byte[] encodedCurrentTimeUTC = Encoding.UTF8.GetBytes(currentTimeUTC);
var options = new DistributedCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromSeconds(20));
await _cache.SetAsync("cachedTimeUTC", encodedCurrentTimeUTC, options);
return RedirectToPage();
}
}
不需要針對具有內建實作的 IDistributedCache 執行個體使用 Singleton 或 Scoped 存留期。
如果您可能需要 IDistributedCache 執行個體而不想使用 DI,那麼也可以建立一個,但透過程式碼建立執行個體可能會讓您的程式碼更加難以測試,而且這種做法也違反了明確相依性原則。
Recommendations
決定哪一個 IDistributedCache 實作最適合您的應用程式時,請考慮下列事項:
- 現有的基礎結構
- 效能需求
- Cost
- 小組體驗
快取解決方案通常依賴記憶體內部儲存體來快速擷取快取的資料,但記憶體是有限的資源,而且成本高昂。 請只將常用的資料儲存在快取中。
對於大部分的應用程式,Redis 快取相比 SQL Server 快取,輸送量更高且延遲更低。 不過,還是建議使用效能評定來判斷快取策略的效能特性。
當 SQL Server 當做分散式快取備份存放區使用時,針對快取使用相同的資料庫和應用程式的一般資料儲存體和擷取可能會對兩者的效能產生負面影響。 我們建議針對分散式快取備份存放區使用專用 SQL Server 執行個體。
其他資源
- Azure 上的 Azure Cache for Redis
- Azure 上的 SQL Database
- 適用於 PostgreSQL 的 Azure 資料庫
- Web 伺服陣列中適用於 NCache 的 ASP.NET Core IDistributedCache 提供者 (GitHub 上的 NCache)
- Microsoft.Extensions.Caching.Cosmos 的存放庫讀我檔案
- ASP.NET Core 中的記憶體內部快取
- 在 ASP.NET Core 中使用變更權杖來偵測變更
- ASP.NET Core 中的回應快取
- ASP.NET Core 中的回應快取中介軟體
- ASP.NET Core MVC 中的快取標籤協助程式
- ASP.NET Core 中的分散式快取標籤協助程式
- 在 Web 伺服陣列上裝載 ASP.NET Core
分散式快取是由多個應用程式伺服器共用的快取,通常作為外部服務 (相對於對快取進行存取的應用程式伺服器) 進行維護。 分散式快取可以改善 ASP.NET Core 應用程式的效能和可擴縮性,尤其是當應用程式是由雲端服務或伺服器陣列裝載時。
分散式快取相比其他快取案例有幾項優點:快取資料會儲存在個別的應用程式伺服器上。
當快取資料散發時,資料具備如下特徵:
- 在多個伺服器的要求之間具備一致性。
- 在伺服器重新啟動和應用程式部署後仍然存續。
- 不使用本機記憶體。
分散式快取組態是特定與實作。 本文說明如何設定 SQL Server、Redis 和 Postgres 分散式快取。 協力廠商實作也可供使用,例如:NCache (NCache on GitHub)。 無論選取哪一個實作,應用程式都會使用 IDistributedCache 介面與快取互動。
檢視或下載範例程式碼 \(英文\) (如何下載)
Prerequisites
為使用的分散式快取提供者新增套件參考:
針對 Redis 分散式快取,Microsoft.Extensions.Caching.StackExchangeRedis。
針對 SQL Server,Microsoft.Extensions.Caching.SqlServer。
針對 Postgres,使用 Microsoft.Extensions.Caching.Postgres。
針對 NCache 分散式快取,NCache.Microsoft.Extensions.Caching.OpenSource。
-
Warning
本文使用本機資料庫,其不需要使用者進行驗證。 實際執行應用程式應該使用可用的最安全驗證流程。 如需已部署測試與實際執行應用程式驗證的詳細資訊,請參閱安全驗證流程。
IDistributedCache 介面
IDistributedCache 介面提供下列方法來操作分散式快取實作中的項目:
-
Get、GetAsync:接受字串索引鍵,並在快取中找到時擷取快取項目做為
byte[]陣列。 -
Set、SetAsync:使用字串索引鍵將項目 (作為
byte[]陣列) 新增至快取。 - Refresh、RefreshAsync:根據快取索引鍵重新整理快取中的項目,重設滑動期限逾時 (如有)。
- Remove、RemoveAsync:移除快取項目 (根據其字串索引鍵)。
建立分散式快取服務
在 IDistributedCache 中註冊 Program.cs 實作。 本主題中所述了下列由架構提供的實作:
分散式 Redis 快取
我們建議生產應用程式使用分散式 Redis 快取,因為它是效能最高的應用程式。 如需詳細資訊,請參閱建議。
Redis 是一種開放原始碼的記憶體內部資料存放區,通常用來作為分散式快取。 您可以為 Azure 裝載的 ASP.NET Core 應用程式設定 Azure Redis Cache,並可使用 Azure Redis Cache 進行本機開發。
應用程式會使用 RedisCache 執行個體 (AddStackExchangeRedisCache) 來設定快取實作。
- 建立 Azure Cache for Redis。
- 將主要連接字串 (StackExchange.Redis) 複製到 Configuration。
- 本機開發:使用秘密管理員儲存連接字串。
- Azure:將連接字串儲存在安全存放區中,例如 Azure Key Vault
下列程式碼會啟用 Azure Cache for Redis:
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = builder.Configuration.GetConnectionString("MyRedisConStr");
options.InstanceName = "SampleInstance";
});
上述程式碼假設主要連接字串 (StackExchange.Redis) 已儲存在組態中,且金鑰名稱為 MyRedisConStr。
如需詳細資訊,請參閱 Azure Cache for Redis。
如需瞭解有關本機 Redis 快取替代方法的討論,請參閱此 GitHub 問題。
分散式記憶體快取
分散式記憶體快取 (AddDistributedMemoryCache) 是架構提供的 IDistributedCache 實作,會將項目儲存在記憶體中。 分散式記憶體快取並非實際的分散式快取。 快取項目會由應用程式執行個體儲存在應用程式執行所在的伺服器上。
分散式記憶體快取是實用的實作:
- 在開發和測試案例中。
- 當單一伺服器用於生產環境而且記憶體耗用量不是問題時。 實作分散式記憶體快取會擷取快取的資料儲存體。 如果需要多個節點或容錯,它可在未來實作真正的分散式快取解決方案。
當應用程式在 Program.cs 的開發環境中執行時,範例應用程式會使用分散式記憶體快取:
builder.Services.AddDistributedMemoryCache();
分散式 SQL Server 快取
分散式 SQL Server 快取實作 (AddDistributedSqlServerCache) 可讓分散式快取使用 SQL Server 資料庫作為其備份存放區。 若要在 SQL Server 執行個體中建立 SQL Server 快取項目資料表,您可以使用 sql-cache 工具。 此工具會使用您指定的名稱和架構來建立資料表。
執行 sql-cache create 命令以在 SQL Server 中建立資料表。 提供 SQL Server 執行個體 (Data Source)、資料庫 (Initial Catalog)、架構 (例如,dbo) 以及資料表名稱 (例如,TestCache):
dotnet sql-cache create "Data Source=(localdb)/MSSQLLocalDB;Initial Catalog=DistCache;Integrated Security=True;" dbo TestCache
系統將記錄訊息,指出工具成功:
Table and index were created successfully.
sql-cache 工具所建立的資料表具有下列架構:
Note
應用程式應該使用 IDistributedCache 的執行個體來操作快取值,而不是 SqlServerCache。
範例應用程式會在 SqlServerCache 中的非開發環境中實作 Program.cs:
builder.Services.AddDistributedSqlServerCache(options =>
{
options.ConnectionString = builder.Configuration.GetConnectionString(
"DistCache_ConnectionString");
options.SchemaName = "dbo";
options.TableName = "TestCache";
});
Note
ConnectionString(選擇性地,SchemaName 和 TableName) 通常儲存在原始檔控制之外 (例如,由秘密管理員儲存,或儲存在 appsettings.json/appsettings.{Environment}.json 檔案中)。 連接字串可能包含應不保留在原始檔控制系統中的認證。
分散式 Postgres 快取
適用於PostgreSQL的 Azure 資料庫 可透過介面作為分散式快取備份存放區 IDistributedCache 。 適用於 PostgreSQL 的 Azure 資料庫是完全受控、AI 就緒的資料庫即服務 (DBaaS) 供應專案,建置在開放原始碼 PostgreSQL 引擎上,其設計目的是支援具有可預測效能、強固安全性、高可用性和無縫延展性的任務關鍵性工作負載。
安裝 Microsoft.Extensions.Caching.Postgres NuGet 套件之後,請設定分散式快取,如下所示:
- 註冊服務
using Microsoft.Extensions.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
// Register Postgres distributed cache
builder.Services.AddDistributedPostgresCache(options => {
options.ConnectionString = builder.Configuration.GetConnectionString("PostgresCache");
options.SchemaName = builder.Configuration.GetValue<string>("PostgresCache:SchemaName", "public");
options.TableName = builder.Configuration.GetValue<string>("PostgresCache:TableName", "cache");
options.CreateIfNotExists = builder.Configuration.GetValue<bool>("PostgresCache:CreateIfNotExists", true);
options.UseWAL = builder.Configuration.GetValue<bool>("PostgresCache:UseWAL", false);
// Optional: Configure expiration settings
var expirationInterval = builder.Configuration.GetValue<string>("PostgresCache:ExpiredItemsDeletionInterval");
if (!string.IsNullOrEmpty(expirationInterval) && TimeSpan.TryParse(expirationInterval, out var interval)) {
options.ExpiredItemsDeletionInterval = interval;
}
var slidingExpiration = builder.Configuration.GetValue<string>("PostgresCache:DefaultSlidingExpiration");
if (!string.IsNullOrEmpty(slidingExpiration) && TimeSpan.TryParse(slidingExpiration, out var sliding)) {
options.DefaultSlidingExpiration = sliding;
}
});
var app = builder.Build();
- 使用快取
public class MyService {
private readonly IDistributedCache _cache;
public MyService(IDistributedCache cache) {
_cache = cache;
}
public async Task<string> GetDataAsync(string key) {
var cachedData = await _cache.GetStringAsync(key);
if (cachedData == null) {
// Fetch data from source
var data = await FetchDataFromSource();
// Cache the data with options
var options = new DistributedCacheEntryOptions {
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30),
SlidingExpiration = TimeSpan.FromMinutes(5)
};
await _cache.SetStringAsync(key, data, options);
return data;
}
return cachedData;
}
}
分散式 NCache 快取
NCache 是在 .NET 和 .NET Core 中原生開發的開放原始碼記憶體中分散式快取。 NCache 可在本機運作,對於在 Azure 或其他裝載平臺上執行的 ASP.NET Core 應用程式,則設定為分散式快取叢集。
若要在本機電腦上安裝和設定 NCache,請參閱 Windows 使用者入門指南 (.NET 和 .NET Core)。
若要設定 NCache:
- 安裝 NCache 開放原始碼 NuGet。
- 在 client.ncconf 中設定快取叢集。
- 將下列程式碼新增至
Program.cs:
builder.Services.AddNCacheDistributedCache(configuration =>
{
configuration.CacheName = "democache";
configuration.EnableLogs = true;
configuration.ExceptionsEnabled = true;
});
使用分散式快取
若要使用 IDistributedCache 介面,請在應用程式中要求 IDistributedCache 的執行個體。 執行個體是由相依性插入 (DI) 提供。
當範例應用程式啟動時,IDistributedCache 會插入至 Program.cs。 目前的時間會使用 IHostApplicationLifetime 快取 (如需詳細資訊,請參閱一般主機:IHostApplicationLifetime):
app.Lifetime.ApplicationStarted.Register(() =>
{
var currentTimeUTC = DateTime.UtcNow.ToString();
byte[] encodedCurrentTimeUTC = System.Text.Encoding.UTF8.GetBytes(currentTimeUTC);
var options = new DistributedCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromSeconds(20));
app.Services.GetService<IDistributedCache>()
.Set("cachedTimeUTC", encodedCurrentTimeUTC, options);
});
範例應用程式會將 IDistributedCache 插入 IndexModel,以供 [索引] 頁面使用。
每次載入索引頁面時,都會檢查快取是否存在 OnGetAsync 中的快取時間。 如果快取的時間尚未過期,則會顯示時間。 如果自上次存取快取時間之後已經過 20 秒 (上次載入此頁面的時間),頁面會顯示 [快取時間過期]。
選取 [重設快取時間] 按鈕可立即將快取的時間更新為目前時間。 此按鈕會觸發 OnPostResetCachedTime 處理常式方法。
public class IndexModel : PageModel
{
private readonly IDistributedCache _cache;
public IndexModel(IDistributedCache cache)
{
_cache = cache;
}
public string? CachedTimeUTC { get; set; }
public string? ASP_Environment { get; set; }
public async Task OnGetAsync()
{
CachedTimeUTC = "Cached Time Expired";
var encodedCachedTimeUTC = await _cache.GetAsync("cachedTimeUTC");
if (encodedCachedTimeUTC != null)
{
CachedTimeUTC = Encoding.UTF8.GetString(encodedCachedTimeUTC);
}
ASP_Environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
if (String.IsNullOrEmpty(ASP_Environment))
{
ASP_Environment = "Null, so Production";
}
}
public async Task<IActionResult> OnPostResetCachedTime()
{
var currentTimeUTC = DateTime.UtcNow.ToString();
byte[] encodedCurrentTimeUTC = Encoding.UTF8.GetBytes(currentTimeUTC);
var options = new DistributedCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromSeconds(20));
await _cache.SetAsync("cachedTimeUTC", encodedCurrentTimeUTC, options);
return RedirectToPage();
}
}
不需要針對具有內建實作的 IDistributedCache 執行個體使用 Singleton 或 Scoped 存留期。
如果您可能需要 IDistributedCache 執行個體而不想使用 DI,那麼也可以建立一個,但透過程式碼建立執行個體可能會讓您的程式碼更加難以測試,而且這種做法也違反了明確相依性原則。
Recommendations
決定哪一個 IDistributedCache 實作最適合您的應用程式時,請考慮下列事項:
- 現有的基礎結構
- 效能需求
- Cost
- 小組體驗
快取解決方案通常依賴記憶體內部儲存體來快速擷取快取的資料,但記憶體是有限的資源,而且成本高昂。 請只將常用的資料儲存在快取中。
對於大部分的應用程式,Redis 快取相比 SQL Server 快取,輸送量更高且延遲更低。 不過,還是建議使用效能評定來判斷快取策略的效能特性。
當 SQL Server 當做分散式快取備份存放區使用時,針對快取使用相同的資料庫和應用程式的一般資料儲存體和擷取可能會對兩者的效能產生負面影響。 我們建議針對分散式快取備份存放區使用專用 SQL Server 執行個體。
其他資源
- Azure 上的 Azure Cache for Redis
- Azure 上的 SQL Database
- 適用於 PostgreSQL 的 Azure 資料庫
- Web 伺服陣列中適用於 NCache 的 ASP.NET Core IDistributedCache 提供者 (GitHub 上的 NCache)
- ASP.NET Core 中的記憶體內部快取
- 在 ASP.NET Core 中使用變更權杖來偵測變更
- ASP.NET Core 中的回應快取
- ASP.NET Core 中的回應快取中介軟體
- ASP.NET Core MVC 中的快取標籤協助程式
- ASP.NET Core 中的分散式快取標籤協助程式
- 在 Web 伺服陣列上裝載 ASP.NET Core
分散式快取是由多個應用程式伺服器共用的快取,通常作為外部服務 (相對於對快取進行存取的應用程式伺服器) 進行維護。 分散式快取可以改善 ASP.NET Core 應用程式的效能和可擴縮性,尤其是當應用程式是由雲端服務或伺服器陣列裝載時。
分散式快取相比其他快取案例有幾項優點:快取資料會儲存在個別的應用程式伺服器上。
當快取資料散發時,資料具備如下特徵:
- 在多個伺服器的要求之間具備一致性。
- 在伺服器重新啟動和應用程式部署後仍然存續。
- 不使用本機記憶體。
分散式快取組態是特定與實作。 本文說明如何設定 SQL Server、Redis 和 Postgres 分散式快取。 協力廠商實作也可供使用,例如:NCache (NCache on GitHub)。 無論選取哪一個實作,應用程式都會使用 IDistributedCache 介面與快取互動。
檢視或下載範例程式碼 \(英文\) (如何下載)
Prerequisites
若要使用 SQL Server 分散式快取,請將套件參考新增至 Microsoft.Extensions.Caching.SqlServer 套件。
若要使用 Redis 分散式快取,請將套件參考新增至 Microsoft.Extensions.Caching.StackExchangeRedis 套件。
若要使用 Postgres 分散式快取,請將套件參考新增至 Microsoft.Extensions.Caching.Postgres 套件。
若要使用 NCache 分散式快取,請將套件參考新增至 NCache.Microsoft.Extensions.Caching.OpenSource 套件。
IDistributedCache 介面
IDistributedCache 介面提供下列方法來操作分散式快取實作中的項目:
-
Get、GetAsync:接受字串索引鍵,並在快取中找到時擷取快取項目做為
byte[]陣列。 -
Set、SetAsync:使用字串索引鍵將項目 (作為
byte[]陣列) 新增至快取。 - Refresh、RefreshAsync:根據快取索引鍵重新整理快取中的項目,重設滑動期限逾時 (如有)。
- Remove、RemoveAsync:移除快取項目 (根據其字串索引鍵)。
建立分散式快取服務
在 IDistributedCache 中註冊 Startup.ConfigureServices 實作。 本主題中所述了下列由架構提供的實作:
分散式記憶體快取
分散式記憶體快取 (AddDistributedMemoryCache) 是架構提供的 IDistributedCache 實作,會將項目儲存在記憶體中。 分散式記憶體快取並非實際的分散式快取。 快取項目會由應用程式執行個體儲存在應用程式執行所在的伺服器上。
分散式記憶體快取是實用的實作:
- 在開發和測試案例中。
- 當單一伺服器用於生產環境而且記憶體耗用量不是問題時。 實作分散式記憶體快取會擷取快取的資料儲存體。 如果需要多個節點或容錯,它可在未來實作真正的分散式快取解決方案。
當應用程式在 Startup.ConfigureServices 的開發環境中執行時,範例應用程式會使用分散式記憶體快取:
services.AddDistributedMemoryCache();
分散式 SQL Server 快取
分散式 SQL Server 快取實作 (AddDistributedSqlServerCache) 可讓分散式快取使用 SQL Server 資料庫作為其備份存放區。 若要在 SQL Server 執行個體中建立 SQL Server 快取項目資料表,您可以使用 sql-cache 工具。 此工具會使用您指定的名稱和架構來建立資料表。
執行 sql-cache create 命令以在 SQL Server 中建立資料表。 提供 SQL Server 執行個體 (Data Source)、資料庫 (Initial Catalog)、架構 (例如,dbo) 以及資料表名稱 (例如,TestCache):
dotnet sql-cache create "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=DistCache;Integrated Security=True;" dbo TestCache
系統將記錄訊息,指出工具成功:
Table and index were created successfully.
sql-cache 工具所建立的資料表具有下列架構:
Note
應用程式應該使用 IDistributedCache 的執行個體來操作快取值,而不是 SqlServerCache。
範例應用程式會在 SqlServerCache 中的非開發環境中實作 Startup.ConfigureServices:
services.AddDistributedSqlServerCache(options =>
{
options.ConnectionString =
_config["DistCache_ConnectionString"];
options.SchemaName = "dbo";
options.TableName = "TestCache";
});
Note
ConnectionString(選擇性地,SchemaName 和 TableName) 通常儲存在原始檔控制之外 (例如,由秘密管理員儲存,或儲存在 appsettings.json/appsettings.{Environment}.json 檔案中)。 連接字串可能包含應不保留在原始檔控制系統中的認證。
分散式 Redis 快取
Redis 是一種開放原始碼的記憶體內部資料存放區,通常用來作為分散式快取。 您可以為 Azure 裝載的 ASP.NET Core 應用程式設定 Azure Redis Cache,並可使用 Azure Redis Cache 進行本機開發。
應用程式會使用 RedisCache 執行個體 (AddStackExchangeRedisCache) 來設定快取實作。
- 建立 Azure Cache for Redis。
- 將主要連接字串 (StackExchange.Redis) 複製到 Configuration。
- 本機開發:使用秘密管理員儲存連接字串。
- Azure:將連接字串儲存在安全存放區中,例如 Azure Key Vault
下列程式碼會啟用 Azure Cache for Redis:
public void ConfigureServices(IServiceCollection services)
{
if (_hostContext.IsDevelopment())
{
services.AddDistributedMemoryCache();
}
else
{
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = _config["MyRedisConStr"];
options.InstanceName = "SampleInstance";
});
}
services.AddRazorPages();
}
上述程式碼假設主要連接字串 (StackExchange.Redis) 已儲存在組態中,且金鑰名稱為 MyRedisConStr。
如需詳細資訊,請參閱 Azure Cache for Redis。
如需瞭解有關本機 Redis 快取替代方法的討論,請參閱此 GitHub 問題。
分散式 Postgres 快取
適用於PostgreSQL的 Azure 資料庫 可透過介面作為分散式快取備份存放區 IDistributedCache 。 適用於 PostgreSQL 的 Azure 資料庫是完全受控、AI 就緒的資料庫即服務 (DBaaS) 供應專案,建置在開放原始碼 PostgreSQL 引擎上,其設計目的是支援具有可預測效能、強固安全性、高可用性和無縫延展性的任務關鍵性工作負載。
安裝 Microsoft.Extensions.Caching.Postgres NuGet 套件之後,請設定分散式快取,如下所示:
- 註冊服務
using Microsoft.Extensions.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
// Register Postgres distributed cache
builder.Services.AddDistributedPostgresCache(options => {
options.ConnectionString = builder.Configuration.GetConnectionString("PostgresCache");
options.SchemaName = builder.Configuration.GetValue<string>("PostgresCache:SchemaName", "public");
options.TableName = builder.Configuration.GetValue<string>("PostgresCache:TableName", "cache");
options.CreateIfNotExists = builder.Configuration.GetValue<bool>("PostgresCache:CreateIfNotExists", true);
options.UseWAL = builder.Configuration.GetValue<bool>("PostgresCache:UseWAL", false);
// Optional: Configure expiration settings
var expirationInterval = builder.Configuration.GetValue<string>("PostgresCache:ExpiredItemsDeletionInterval");
if (!string.IsNullOrEmpty(expirationInterval) && TimeSpan.TryParse(expirationInterval, out var interval)) {
options.ExpiredItemsDeletionInterval = interval;
}
var slidingExpiration = builder.Configuration.GetValue<string>("PostgresCache:DefaultSlidingExpiration");
if (!string.IsNullOrEmpty(slidingExpiration) && TimeSpan.TryParse(slidingExpiration, out var sliding)) {
options.DefaultSlidingExpiration = sliding;
}
});
var app = builder.Build();
- 使用快取
public class MyService {
private readonly IDistributedCache _cache;
public MyService(IDistributedCache cache) {
_cache = cache;
}
public async Task<string> GetDataAsync(string key) {
var cachedData = await _cache.GetStringAsync(key);
if (cachedData == null) {
// Fetch data from source
var data = await FetchDataFromSource();
// Cache the data with options
var options = new DistributedCacheEntryOptions {
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30),
SlidingExpiration = TimeSpan.FromMinutes(5)
};
await _cache.SetStringAsync(key, data, options);
return data;
}
return cachedData;
}
}
分散式 NCache 快取
NCache 是在 .NET 和 .NET Core 中原生開發的開放原始碼記憶體中分散式快取。 NCache 可在本機運作,對於在 Azure 或其他裝載平臺上執行的 ASP.NET Core 應用程式,則設定為分散式快取叢集。
若要在本機電腦上安裝和設定 NCache,請參閱 Windows 使用者入門指南 (.NET 和 .NET Core)。
若要設定 NCache:
在 client.ncconf 中設定快取叢集。
將下列程式碼新增至
Startup.ConfigureServices:services.AddNCacheDistributedCache(configuration => { configuration.CacheName = "demoClusteredCache"; configuration.EnableLogs = true; configuration.ExceptionsEnabled = true; });
使用分散式快取
若要使用 IDistributedCache 介面,請向應用程式中的任何建構函式要求 IDistributedCache 執行個體。 執行個體是由相依性插入 (DI) 提供。
當範例應用程式啟動時,IDistributedCache 會插入至 Startup.Configure。 目前的時間會使用 IHostApplicationLifetime 快取 (如需詳細資訊,請參閱一般主機:IHostApplicationLifetime):
public void Configure(IApplicationBuilder app, IWebHostEnvironment env,
IHostApplicationLifetime lifetime, IDistributedCache cache)
{
lifetime.ApplicationStarted.Register(() =>
{
var currentTimeUTC = DateTime.UtcNow.ToString();
byte[] encodedCurrentTimeUTC = Encoding.UTF8.GetBytes(currentTimeUTC);
var options = new DistributedCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromSeconds(20));
cache.Set("cachedTimeUTC", encodedCurrentTimeUTC, options);
});
範例應用程式會將 IDistributedCache 插入 IndexModel,以供 [索引] 頁面使用。
每次載入索引頁面時,都會檢查快取是否存在 OnGetAsync 中的快取時間。 如果快取的時間尚未過期,則會顯示時間。 如果自上次存取快取時間之後已經過 20 秒 (上次載入此頁面的時間),頁面會顯示 [快取時間過期]。
選取 [重設快取時間] 按鈕可立即將快取的時間更新為目前時間。 此按鈕會觸發 OnPostResetCachedTime 處理常式方法。
public class IndexModel : PageModel
{
private readonly IDistributedCache _cache;
public IndexModel(IDistributedCache cache)
{
_cache = cache;
}
public string CachedTimeUTC { get; set; }
public async Task OnGetAsync()
{
CachedTimeUTC = "Cached Time Expired";
var encodedCachedTimeUTC = await _cache.GetAsync("cachedTimeUTC");
if (encodedCachedTimeUTC != null)
{
CachedTimeUTC = Encoding.UTF8.GetString(encodedCachedTimeUTC);
}
}
public async Task<IActionResult> OnPostResetCachedTime()
{
var currentTimeUTC = DateTime.UtcNow.ToString();
byte[] encodedCurrentTimeUTC = Encoding.UTF8.GetBytes(currentTimeUTC);
var options = new DistributedCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromSeconds(20));
await _cache.SetAsync("cachedTimeUTC", encodedCurrentTimeUTC, options);
return RedirectToPage();
}
}
Note
不需要針對 IDistributedCache 執行個體使用 Singleton 或 Scoped 存留期 (至少針對內建實作)。
如果您可能需要 IDistributedCache 執行個體而不想使用 DI,那麼也可以建立一個,但透過程式碼建立執行個體可能會讓您的程式碼更加難以測試,而且這種做法也違反了明確相依性原則。
Recommendations
決定哪一個 IDistributedCache 實作最適合您的應用程式時,請考慮下列事項:
- 現有的基礎結構
- 效能需求
- Cost
- 小組體驗
快取解決方案通常依賴記憶體內部儲存體來快速擷取快取的資料,但記憶體是有限的資源,而且成本高昂。 請只將常用的資料儲存在快取中。
一般而言,Redis 快取相比 SQL Server 快取,輸送量更高且延遲更低。 不過,通常還是需要使用效能評定來判斷快取策略的效能特性。
當 SQL Server 當做分散式快取備份存放區使用時,針對快取使用相同的資料庫和應用程式的一般資料儲存體和擷取可能會對兩者的效能產生負面影響。 我們建議針對分散式快取備份存放區使用專用 SQL Server 執行個體。
其他資源
- Azure 上的 Azure Cache for Redis
- Azure 上的 SQL Database
- 適用於 PostgreSQL 的 Azure 資料庫
- Web 伺服陣列中適用於 NCache 的 ASP.NET Core IDistributedCache 提供者 (GitHub 上的 NCache)
- ASP.NET Core 中的記憶體內部快取
- 在 ASP.NET Core 中使用變更權杖來偵測變更
- ASP.NET Core 中的回應快取
- ASP.NET Core 中的回應快取中介軟體
- ASP.NET Core MVC 中的快取標籤協助程式
- ASP.NET Core 中的分散式快取標籤協助程式
- 在 Web 伺服陣列上裝載 ASP.NET Core