ASP.NET Core 中的 HybridCache 程式庫
重要
HybridCache
目前仍處於預覽狀態,但在 .NET 9.0 之後將在未來的 .NET 延伸模組次要版本中完全發行。
本文說明如何在 ASP.NET Core 應用程式中設定和使用 HybridCache
程式庫。 如需程式庫的簡介,請參閱快取概觀的 HybridCache
區段。
取得程式庫
安裝 Microsoft.Extensions.Caching.Hybrid
套件。
dotnet add package Microsoft.Extensions.Caching.Hybrid --version "9.0.0-preview.7.24406.2"
註冊服務
藉由呼叫 AddHybridCache
,將 HybridCache
服務新增至相依性插入 (DI) 容器:
// Add services to the container.
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddAuthorization();
builder.Services.AddHybridCache();
上述程式碼會使用預設選項註冊 HybridCache
服務。 註冊 API 也可以設定選項和序列化。
取得和儲存快取項目
此 HybridCache
服務提供兩個使用多載的 GetOrCreateAsync
方法,採用索引鍵和:
- Factory 方法。
- 狀態和 Factory 方法。
方法會使用索引鍵嘗試從主要快取擷取物件。 如果在主要快取中找不到項目 (快取遺失),則會檢查是否已設定次要快取。 如果找不到該處的資料 (另一個快取遺失),它會呼叫 Factory 方法,以從資料來源取得物件。 然後,它會將物件儲存在主要和次要快取中。 如果在主要或次要快取中找到物件 (快取命中),則永遠不會呼叫 Factory 方法。
HybridCache
服務可確保只有一個指定機碼的同時呼叫端會呼叫 Factory 方法,而所有其他呼叫端都會等候該呼叫的結果。 傳遞至 GetOrCreateAsync
的 CancellationToken
代表所有同時呼叫端的合併取消。
主要 GetOrCreateAsync
多載
在大部分情況下,建議使用 GetOrCreateAsync
的無狀態多載。 要呼叫的程式碼相對簡單。 以下是範例:
public class SomeService(HybridCache cache)
{
private HybridCache _cache = cache;
public async Task<string> GetSomeInfoAsync(string name, int id, CancellationToken token = default)
{
return await _cache.GetOrCreateAsync(
$"{name}-{id}", // Unique key to the cache entry
async cancel => await GetDataFromTheSourceAsync(name, id, cancel),
cancellationToken: token
);
}
public async Task<string> GetDataFromTheSourceAsync(string name, int id, CancellationToken token)
{
string someInfo = $"someinfo-{name}-{id}";
return someInfo;
}
}
替代 GetOrCreateAsync
多載
替代多載可能會降低擷取到的變數和個別執行個體回呼的一些額外負荷,但代價是更複雜的程式碼。 在大部分情況下,效能提升不會比程式碼的複雜度更重要。 以下是使用替代多載的範例:
public class SomeService(HybridCache cache)
{
private HybridCache _cache = cache;
public async Task<string> GetSomeInfoAsync(string name, int id, CancellationToken token = default)
{
return await _cache.GetOrCreateAsync(
$"{name}-{id}", // Unique key to the cache entry
(name, id, obj: this),
static async (state, token) =>
await state.obj.GetDataFromTheSourceAsync(state.name, state.id, token),
cancellationToken: token
);
}
public async Task<string> GetDataFromTheSourceAsync(string name, int id, CancellationToken token)
{
string someInfo = $"someinfo-{name}-{id}";
return someInfo;
}
}
SetAsync
方法
在許多情況下,GetOrCreateAsync
是唯一需要的 API。 但 HybridCache
也必須具有 SetAsync
以將物件儲存在快取中,而不需要先嘗試擷取它。
依機碼移除快取項目
當快取項目的基礎資料在到期前變更時,可透過叫用帶有機碼 RemoveAsync
至項目以明確移除該項目。 多載 (英文) 可讓您指定機碼的集合。
移除項目時,它會從主要和次要快取中移除。
依標籤移除快取項目
標籤可用來將快取項目分組,並使其一起失效。
呼叫 GetOrCreateAsync
時設定標籤,如下列範例所示:
public class SomeService(HybridCache cache)
{
private HybridCache _cache = cache;
public async Task<string> GetSomeInfoAsync(string name, int id, CancellationToken token = default)
{
var tags = new List<string> { "tag1", "tag2", "tag3" };
var entryOptions = new HybridCacheEntryOptions
{
Expiration = TimeSpan.FromMinutes(1),
LocalCacheExpiration = TimeSpan.FromMinutes(1)
};
return await _cache.GetOrCreateAsync(
$"{name}-{id}", // Unique key to the cache entry
async cancel => await GetDataFromTheSourceAsync(name, id, cancel),
entryOptions,
tags,
cancellationToken: token
);
}
public async Task<string> GetDataFromTheSourceAsync(string name, int id, CancellationToken token)
{
string someInfo = $"someinfo-{name}-{id}";
return someInfo;
}
}
使用標籤值呼叫 RemoveByTagAsync
,以移除指定標籤的所有項目。 多載 (英文) 可讓您指定標籤的集合。
移除項目時,它會從主要和次要快取中移除。
選項。
AddHybridCache
方法可用來設定全域預設值。 下列範例示範如何設定一些可用的選項:
// Add services to the container.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthorization();
builder.Services.AddHybridCache(options =>
{
options.MaximumPayloadBytes = 1024 * 1024;
options.MaximumKeyLength = 1024;
options.DefaultEntryOptions = new HybridCacheEntryOptions
{
Expiration = TimeSpan.FromMinutes(5),
LocalCacheExpiration = TimeSpan.FromMinutes(5)
};
});
GetOrCreateAsync
方法也可以採用 HybridCacheEntryOptions
物件來覆寫特定快取項目的全域預設值。 以下是範例:
public class SomeService(HybridCache cache)
{
private HybridCache _cache = cache;
public async Task<string> GetSomeInfoAsync(string name, int id, CancellationToken token = default)
{
var tags = new List<string> { "tag1", "tag2", "tag3" };
var entryOptions = new HybridCacheEntryOptions
{
Expiration = TimeSpan.FromMinutes(1),
LocalCacheExpiration = TimeSpan.FromMinutes(1)
};
return await _cache.GetOrCreateAsync(
$"{name}-{id}", // Unique key to the cache entry
async cancel => await GetDataFromTheSourceAsync(name, id, cancel),
entryOptions,
tags,
cancellationToken: token
);
}
public async Task<string> GetDataFromTheSourceAsync(string name, int id, CancellationToken token)
{
string someInfo = $"someinfo-{name}-{id}";
return someInfo;
}
}
如需選項的詳細資訊,請參閱原始程式碼:
限制
下列 HybridCacheOptions
屬性可讓您設定適用於所有快取項目的限制:
- MaximumPayloadBytes - 快取項目的大小上限。 預設值為 1 MB。 系統會記錄嘗試儲存超過此大小的值,且該值不會儲存在快取中。
- MaximumKeyLength - 快取索引鍵的最大長度。 預設值為 1024 個字元。 系統會記錄嘗試儲存超過此大小的值,且該值不會儲存在快取中。
序列化
使用次要的跨處理序快取需要序列化。 序列化設定為註冊 HybridCache
服務的一部分。 類型特定和一般用途序列化程式可以透過 AddSerializer
和 AddSerializerFactory
方法進行設定,並從 AddHybridCache
呼叫鏈結。 根據預設,程式庫會在內部處理 string
和 byte[]
,並針對其他所有項目使用 System.Text.Json
。 HybridCache
也可以使用其他序列化程式,例如 protobuf 或 XML。
下列範例會將服務設定為使用類型特定的 protobuf 序列化程式:
// Add services to the container.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthorization();
builder.Services.AddHybridCache(options =>
{
options.DefaultEntryOptions = new HybridCacheEntryOptions
{
Expiration = TimeSpan.FromSeconds(10),
LocalCacheExpiration = TimeSpan.FromSeconds(5)
};
}).AddSerializer<SomeProtobufMessage,
GoogleProtobufSerializer<SomeProtobufMessage>>();
下列範例會將服務設定為使用可處理許多 protobuf 類型的一般用途 protobuf 序列化程式:
// Add services to the container.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthorization();
builder.Services.AddHybridCache(options =>
{
options.DefaultEntryOptions = new HybridCacheEntryOptions
{
Expiration = TimeSpan.FromSeconds(10),
LocalCacheExpiration = TimeSpan.FromSeconds(5)
};
}).AddSerializerFactory<GoogleProtobufSerializerFactory>();
次要快取需要資料存放區,例如 Redis 或 SqlServer。 若要使用 Azure Cache for Redis,例如:
安裝
Microsoft.Extensions.Caching.StackExchangeRedis
套件。建立 Azure Cache for Redis 的執行個體。
取得連線至 Redis 實體的連接字串。 在 Azure 入口網站的 [概觀] 頁面上選取 [顯示存取金鑰],以尋找連接字串。
將連接字串儲存在應用程式的組態中。 例如,使用類似下列 JSON 的使用者祕密檔案,以及
ConnectionStrings
區段中的連接字串。 將<the connection string>
取代為實際的連接字串:{ "ConnectionStrings": { "RedisConnectionString": "<the connection string>" } }
在 DI 中註冊 Redis 套件所提供的
IDistributedCache
實作。 若要這樣做,請呼叫AddStackExchangeRedisCache
,並傳入連接字串。 例如:builder.Services.AddStackExchangeRedisCache(options => { options.Configuration = builder.Configuration.GetConnectionString("RedisConnectionString"); });
Redis
IDistributedCache
實作現在可從應用程式的 DI 容器取得。HybridCache
會使用它作為次要快取,並使用為其設定的序列化程式。
如需詳細資訊,請參閱 HybridCache 序列化範例應用程式。
快取儲存體
根據預設,HybridCache
會針對其主要快取儲存體使用 MemoryCache。 快取項目會以內含式方式儲存,因此每部伺服器都有個別的快取,每當伺服器程序重新啟動時就會遺失。 如果是次要跨進程儲存體,例如 Redis 或 SQL Server,HybridCache
會使用已設定的 IDistributedCache
實作 (如果有的話)。 但即使沒有 IDistributedCache
實作,HybridCache
服務仍會提供內含式快取和踩踏保護。
最佳化效能
若要將效能最佳化,請將 HybridCache
設定為重複使用物件,並避免 byte[]
配置。
重複使用物件
藉由重複使用執行個體,HybridCache
即可降低與每次呼叫的還原序列化相關聯的 CPU 和物件配置額外負荷。 在快取物件很大或受到頻繁存取的案例中,這可以提高效能。
在使用 IDistributedCache
的一般現有程式碼中,每次從快取中擷取物件都會導致還原序列化。 此行為表示每個並行呼叫者都會取得物件的不同執行個體,而該執行個體無法與其他執行個體互動。 結果是執行緒安全性,因為對相同物件執行個體的並行修改不會產生風險。
由於會根據現有的 IDistributedCache
程式碼來調整許多 HybridCache
使用方式,因此 HybridCache
預設會保留此行為,以避免引進並行錯誤 (bug)。 不過,如果下列狀況,物件本質上是安全執行緒:
- 它們具有不變的類型。
- 程式碼不會修改它們。
在這種情況下,請通知 HybridCache
透過下列方式可安全地重複使用執行個體:
- 將類型標示為
sealed
。 C# 中的sealed
關鍵字表示無法繼承該類別。 - 將
[ImmutableObject(true)]
屬性套用至型別。[ImmutableObject(true)]
屬性表示物件的狀態在建立之後即無法變更。
避免 byte[]
配置
HybridCache
也會提供 IDistributedCache
實作的選用 API,以避免 byte[]
配置。 這項功能由 Microsoft.Extensions.Caching.StackExchangeRedis
和 Microsoft.Extensions.Caching.SqlServer
套件的預覽版本實作。 如需詳細資訊,請參閱 IBufferDistributedCache 以下是安裝套件的 .NET CLI 命令:
dotnet add package Microsoft.Extensions.Caching.StackExchangeRedis --prerelease
dotnet add package Microsoft.Extensions.Caching.SqlServer --prerelease
自訂 HybridCache 實作
HybridCache
抽象類別的具體實作包含在共用架構中,並透過相依性插入來提供。 但歡迎開發人員提供 API 的自訂實作。
相容性
HybridCache
程式庫支援舊版 .NET 執行階段,向下至 .NET Framework 4.7.2 和 .NET Standard 2.0。
其他資源
如需 HybridCache
的詳細資訊,請參閱下列資源:
- GitHub 問題 dotnet/aspnetcore #54647。
HybridCache
原始程式碼