ASP.NET Core 中的分散式快取

作者:Mohsin Nasirsmandia

注意

這不是這篇文章的最新版本。 如需目前版本,請參閱本文的 .NET 8 版本

重要

這些發行前產品的相關資訊在產品正式發行前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。

如需目前版本,請參閱本文的 .NET 8 版本

分散式快取是由多個應用程式伺服器共用的快取,通常作為外部服務 (相對於對快取進行存取的應用程式伺服器) 進行維護。 分散式快取可以改善 ASP.NET Core 應用程式的效能和可擴縮性,尤其是當應用程式是由雲端服務或伺服器陣列裝載時。

分散式快取相比其他快取案例有幾項優點:快取資料會儲存在個別的應用程式伺服器上。

當快取資料散發時,資料具備如下特徵:

  • 在多個伺服器的要求之間具備一致性
  • 在伺服器重新啟動和應用程式部署後仍然存續。
  • 不使用本機記憶體。

分散式快取組態是特定與實作。 本文說明如何設定 SQL Server 和 Redis 分散式快取。 協力廠商實作也可供使用,例如:NCache (NCache on GitHub)。 無論選取哪一個實作,應用程式都會使用 IDistributedCache 介面與快取互動。

檢視或下載範例程式碼 \(英文\) (如何下載)

必要條件

為使用的分散式快取提供者新增套件參考:

IDistributedCache 介面

IDistributedCache 介面提供下列方法來操作分散式快取實作中的項目:

  • GetGetAsync:接受字串索引鍵,並在快取中找到時擷取快取項目做為 byte[] 陣列。
  • SetSetAsync:使用字串索引鍵將項目 (作為 byte[] 陣列) 新增至快取。
  • RefreshRefreshAsync:根據快取索引鍵重新整理快取中的項目,重設滑動期限逾時 (如有)。
  • RemoveRemoveAsync:移除快取項目 (根據其字串索引鍵)。

建立分散式快取服務

Program.cs 中註冊 IDistributedCache 實作。 本主題中所述了下列由架構提供的實作:

分散式 Redis 快取

我們建議生產應用程式使用分散式 Redis 快取,因為它是效能最高的應用程式。 如需詳細資訊,請參閱建議

Redis 是一種開放原始碼的記憶體內部資料存放區,通常用來作為分散式快取。 您可以為 Azure 裝載的 ASP.NET Core 應用程式設定 Azure Cache for Redis,並可使用 Azure Cache for Redis 進行本機開發。

應用程式會藉由呼叫 AddStackExchangeRedisCache,使用 RedisCache 執行個體來設定快取實作。 針對輸出快取,請使用 AddStackExchangeRedisOutputCache

  1. 建立 Azure Cache for Redis。
  2. 將主要連接字串 (StackExchange.Redis) 複製到 Configuration
    • 本機開發:使用秘密管理員儲存連接字串。
    • Azure:將連接字串儲存在 App Service 組態或其他安全存放區中。

下列程式碼會啟用 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 工具所建立的資料表具有下列架構:

SqlServer 快取資料表

注意

應用程式應該使用 IDistributedCache 的執行個體來操作快取值,而不是 SqlServerCache

範例應用程式會在 Program.cs 中的非開發環境中實作 SqlServerCache

builder.Services.AddDistributedSqlServerCache(options =>
{
    options.ConnectionString = builder.Configuration.GetConnectionString(
        "DistCache_ConnectionString");
    options.SchemaName = "dbo";
    options.TableName = "TestCache";
});

注意

ConnectionString(選擇性地,SchemaNameTableName) 通常儲存在原始檔控制之外 (例如,由秘密管理員儲存,或儲存在 appsettings.json/appsettings.{Environment}.json 檔案中)。 連接字串可能包含應不保留在原始檔控制系統中的認證。

分散式 NCache 快取

NCache 是在 .NET 和 .NET Core 中原生開發的開放原始碼記憶體中分散式快取。 NCache 可在本機運作,對於在 Azure 或其他裝載平臺上執行的 ASP.NET Core 應用程式,則設定為分散式快取叢集。

若要在本機電腦上安裝和設定 NCache,請參閱 Windows 使用者入門指南 (.NET 和 .NET Core)

若要設定 NCache:

  1. 安裝 NCache 開放原始碼 NuGet
  2. client.ncconf 中設定快取叢集。
  3. 將下列程式碼新增至 Program.cs
builder.Services.AddNCacheDistributedCache(configuration =>
{
    configuration.CacheName = "democache";
    configuration.EnableLogs = true;
    configuration.ExceptionsEnabled = true;
});

分散式 Azure CosmosDB 快取

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,那麼也可以建立一個,但透過程式碼建立執行個體可能會讓您的程式碼更加難以測試,而且這種做法也違反了明確相依性原則

建議

決定哪一個 IDistributedCache 實作最適合您的應用程式時,請考慮下列事項:

  • 現有的基礎結構
  • 效能需求
  • 成本
  • 小組體驗

快取解決方案通常依賴記憶體內部儲存體來快速擷取快取的資料,但記憶體是有限的資源,而且成本高昂。 請只將常用的資料儲存在快取中。

對於大部分的應用程式,Redis 快取相比 SQL Server 快取,輸送量更高且延遲更低。 不過,還是建議使用效能評定來判斷快取策略的效能特性。

當 SQL Server 當做分散式快取備份存放區使用時,針對快取使用相同的資料庫和應用程式的一般資料儲存體和擷取可能會對兩者的效能產生負面影響。 我們建議針對分散式快取備份存放區使用專用 SQL Server 執行個體。

其他資源

分散式快取是由多個應用程式伺服器共用的快取,通常作為外部服務 (相對於對快取進行存取的應用程式伺服器) 進行維護。 分散式快取可以改善 ASP.NET Core 應用程式的效能和可擴縮性,尤其是當應用程式是由雲端服務或伺服器陣列裝載時。

分散式快取相比其他快取案例有幾項優點:快取資料會儲存在個別的應用程式伺服器上。

當快取資料散發時,資料具備如下特徵:

  • 在多個伺服器的要求之間具備一致性
  • 在伺服器重新啟動和應用程式部署後仍然存續。
  • 不使用本機記憶體。

分散式快取組態是特定與實作。 本文說明如何設定 SQL Server 和 Redis 分散式快取。 協力廠商實作也可供使用,例如:NCache (NCache on GitHub)。 無論選取哪一個實作,應用程式都會使用 IDistributedCache 介面與快取互動。

檢視或下載範例程式碼 \(英文\) (如何下載)

必要條件

為使用的分散式快取提供者新增套件參考:

IDistributedCache 介面

IDistributedCache 介面提供下列方法來操作分散式快取實作中的項目:

  • GetGetAsync:接受字串索引鍵,並在快取中找到時擷取快取項目做為 byte[] 陣列。
  • SetSetAsync:使用字串索引鍵將項目 (作為 byte[] 陣列) 新增至快取。
  • RefreshRefreshAsync:根據快取索引鍵重新整理快取中的項目,重設滑動期限逾時 (如有)。
  • RemoveRemoveAsync:移除快取項目 (根據其字串索引鍵)。

建立分散式快取服務

Program.cs 中註冊 IDistributedCache 實作。 本主題中所述了下列由架構提供的實作:

分散式 Redis 快取

我們建議生產應用程式使用分散式 Redis 快取,因為它是效能最高的應用程式。 如需詳細資訊,請參閱建議

Redis 是一種開放原始碼的記憶體內部資料存放區,通常用來作為分散式快取。 您可以為 Azure 裝載的 ASP.NET Core 應用程式設定 Azure Redis Cache,並可使用 Azure Redis Cache 進行本機開發。

應用程式會使用 RedisCache 執行個體 (AddStackExchangeRedisCache) 來設定快取實作。

  1. 建立 Azure Cache for Redis。
  2. 將主要連接字串 (StackExchange.Redis) 複製到 Configuration
    • 本機開發:使用秘密管理員儲存連接字串。
    • Azure:將連接字串儲存在 App Service 組態或其他安全存放區中。

下列程式碼會啟用 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 工具所建立的資料表具有下列架構:

SqlServer 快取資料表

注意

應用程式應該使用 IDistributedCache 的執行個體來操作快取值,而不是 SqlServerCache

範例應用程式會在 Program.cs 中的非開發環境中實作 SqlServerCache

builder.Services.AddDistributedSqlServerCache(options =>
{
    options.ConnectionString = builder.Configuration.GetConnectionString(
        "DistCache_ConnectionString");
    options.SchemaName = "dbo";
    options.TableName = "TestCache";
});

注意

ConnectionString(選擇性地,SchemaNameTableName) 通常儲存在原始檔控制之外 (例如,由秘密管理員儲存,或儲存在 appsettings.json/appsettings.{Environment}.json 檔案中)。 連接字串可能包含應不保留在原始檔控制系統中的認證。

分散式 NCache 快取

NCache 是在 .NET 和 .NET Core 中原生開發的開放原始碼記憶體中分散式快取。 NCache 可在本機運作,對於在 Azure 或其他裝載平臺上執行的 ASP.NET Core 應用程式,則設定為分散式快取叢集。

若要在本機電腦上安裝和設定 NCache,請參閱 Windows 使用者入門指南 (.NET 和 .NET Core)

若要設定 NCache:

  1. 安裝 NCache 開放原始碼 NuGet
  2. client.ncconf 中設定快取叢集。
  3. 將下列程式碼新增至 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,那麼也可以建立一個,但透過程式碼建立執行個體可能會讓您的程式碼更加難以測試,而且這種做法也違反了明確相依性原則

建議

決定哪一個 IDistributedCache 實作最適合您的應用程式時,請考慮下列事項:

  • 現有的基礎結構
  • 效能需求
  • 成本
  • 小組體驗

快取解決方案通常依賴記憶體內部儲存體來快速擷取快取的資料,但記憶體是有限的資源,而且成本高昂。 請只將常用的資料儲存在快取中。

對於大部分的應用程式,Redis 快取相比 SQL Server 快取,輸送量更高且延遲更低。 不過,還是建議使用效能評定來判斷快取策略的效能特性。

當 SQL Server 當做分散式快取備份存放區使用時,針對快取使用相同的資料庫和應用程式的一般資料儲存體和擷取可能會對兩者的效能產生負面影響。 我們建議針對分散式快取備份存放區使用專用 SQL Server 執行個體。

其他資源

分散式快取是由多個應用程式伺服器共用的快取,通常作為外部服務 (相對於對快取進行存取的應用程式伺服器) 進行維護。 分散式快取可以改善 ASP.NET Core 應用程式的效能和可擴縮性,尤其是當應用程式是由雲端服務或伺服器陣列裝載時。

分散式快取相比其他快取案例有幾項優點:快取資料會儲存在個別的應用程式伺服器上。

當快取資料散發時,資料具備如下特徵:

  • 在多個伺服器的要求之間具備一致性
  • 在伺服器重新啟動和應用程式部署後仍然存續。
  • 不使用本機記憶體。

分散式快取組態是特定與實作。 本文說明如何設定 SQL Server 和 Redis 分散式快取。 協力廠商實作也可供使用,例如:NCache (NCache on GitHub)。 無論選取哪一個實作,應用程式都會使用 IDistributedCache 介面與快取互動。

檢視或下載範例程式碼 \(英文\) (如何下載)

必要條件

若要使用 SQL Server 分散式快取,請將套件參考新增至 Microsoft.Extensions.Caching.SqlServer 套件。

若要使用 Redis 分散式快取,請將套件參考新增至 Microsoft.Extensions.Caching.StackExchangeRedis 套件。

若要使用 NCache 分散式快取,請將套件參考新增至 NCache.Microsoft.Extensions.Caching.OpenSource 套件。

IDistributedCache 介面

IDistributedCache 介面提供下列方法來操作分散式快取實作中的項目:

  • GetGetAsync:接受字串索引鍵,並在快取中找到時擷取快取項目做為 byte[] 陣列。
  • SetSetAsync:使用字串索引鍵將項目 (作為 byte[] 陣列) 新增至快取。
  • RefreshRefreshAsync:根據快取索引鍵重新整理快取中的項目,重設滑動期限逾時 (如有)。
  • RemoveRemoveAsync:移除快取項目 (根據其字串索引鍵)。

建立分散式快取服務

Startup.ConfigureServices 中註冊 IDistributedCache 實作。 本主題中所述了下列由架構提供的實作:

分散式記憶體快取

分散式記憶體快取 (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 工具所建立的資料表具有下列架構:

SqlServer 快取資料表

注意

應用程式應該使用 IDistributedCache 的執行個體來操作快取值,而不是 SqlServerCache

範例應用程式會在 Startup.ConfigureServices 中的非開發環境中實作 SqlServerCache

services.AddDistributedSqlServerCache(options =>
{
    options.ConnectionString = 
        _config["DistCache_ConnectionString"];
    options.SchemaName = "dbo";
    options.TableName = "TestCache";
});

注意

ConnectionString(選擇性地,SchemaNameTableName) 通常儲存在原始檔控制之外 (例如,由秘密管理員儲存,或儲存在 appsettings.json/appsettings.{Environment}.json 檔案中)。 連接字串可能包含應不保留在原始檔控制系統中的認證。

分散式 Redis 快取

Redis 是一種開放原始碼的記憶體內部資料存放區,通常用來作為分散式快取。 您可以為 Azure 裝載的 ASP.NET Core 應用程式設定 Azure Redis Cache,並可使用 Azure Redis Cache 進行本機開發。

應用程式會使用 RedisCache 執行個體 (AddStackExchangeRedisCache) 來設定快取實作。

  1. 建立 Azure Cache for Redis。
  2. 將主要連接字串 (StackExchange.Redis) 複製到 Configuration
    • 本機開發:使用秘密管理員儲存連接字串。
    • Azure:將連接字串儲存在 App Service 組態或其他安全存放區中。

下列程式碼會啟用 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 問題

分散式 NCache 快取

NCache 是在 .NET 和 .NET Core 中原生開發的開放原始碼記憶體中分散式快取。 NCache 可在本機運作,對於在 Azure 或其他裝載平臺上執行的 ASP.NET Core 應用程式,則設定為分散式快取叢集。

若要在本機電腦上安裝和設定 NCache,請參閱 Windows 使用者入門指南 (.NET 和 .NET Core)

若要設定 NCache:

  1. 安裝 NCache 開放原始碼 NuGet

  2. client.ncconf 中設定快取叢集。

  3. 將下列程式碼新增至 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();
    }
}

注意

不需要針對 IDistributedCache 執行個體使用 Singleton 或 Scoped 存留期 (至少針對內建實作)。

如果您可能需要 IDistributedCache 執行個體而不想使用 DI,那麼也可以建立一個,但透過程式碼建立執行個體可能會讓您的程式碼更加難以測試,而且這種做法也違反了明確相依性原則

建議

決定哪一個 IDistributedCache 實作最適合您的應用程式時,請考慮下列事項:

  • 現有的基礎結構
  • 效能需求
  • 成本
  • 小組體驗

快取解決方案通常依賴記憶體內部儲存體來快速擷取快取的資料,但記憶體是有限的資源,而且成本高昂。 請只將常用的資料儲存在快取中。

一般而言,Redis 快取相比 SQL Server 快取,輸送量更高且延遲更低。 不過,通常還是需要使用效能評定來判斷快取策略的效能特性。

當 SQL Server 當做分散式快取備份存放區使用時,針對快取使用相同的資料庫和應用程式的一般資料儲存體和擷取可能會對兩者的效能產生負面影響。 我們建議針對分散式快取備份存放區使用專用 SQL Server 執行個體。

其他資源