什麼是快取,在專案中,為了提高資料的讀取速度,我們會對不經常變更但存取頻繁的資料做快取處理,我們常用的快取有:
目前,MasaFramework
為我們提供了以下能力
Assignment.DistributedCache
,並安裝Masa.Contrib.Caching.Distributed.StackExchangeRedis
dotnet new web -o Assignment.DistributedCache
cd Assignment.DistributedCache
dotnet add package Masa.Contrib.Caching.Distributed.StackExchangeRedis --version 0.6.0-rc.5
Redis
設定資訊{
"RedisConfig":{
"Servers":[
{
"Host":"localhost",
"Port":6379
}
],
"DefaultDatabase":3,
"ConnectionPoolSize":10
}
}
Redis
快取,修改Program.cs
var builder = WebApplication.CreateBuilder(args);
//註冊分散式快取
builder.Services.AddDistributedCache(distributedCacheOptions =>
{
distributedCacheOptions.UseStackExchangeRedisCache();//使用分散式Redis快取, 預設使用本地`RedisConfig`下的設定
});
使用分散式快取的資料來源預設為
IOptionsMonitor<RedisConfigurationOptions>
,如果本地未正確在RedisConfig
節點設定快取資訊,且專案中也沒有通過其它方式設定使其支援選項模式,則預設使用的Redis設定為: 地址: localhost、埠:6379,密碼:空,資料庫:db0
User
類,用於接收使用者資訊public class User
{
public string Name { get; set; }
public int Age { get; set; }
}
IDistributedCacheClient
,修改Program.cs
// 設定快取
app.MapPost("/set/{id}", async (IDistributedCacheClient distributedCacheClient, [FromRoute] string id, [FromBody] User user) =>
{
await distributedCacheClient.SetAsync(id, user);
return Results.Accepted();
});
// 獲取快取
app.MapGet("/get/{id}", async (IDistributedCacheClient distributedCacheClient, [FromRoute] string id) =>
{
var value = await distributedCacheClient.GetAsync<User>(id);
return Results.Ok(value);
});
Assignment.DistributedCache
,並安裝Masa.Contrib.Caching.MultilevelCache
、Masa.Contrib.Caching.Distributed.StackExchangeRedis
dotnet new web -o Assignment.MultilevelCache
cd Assignment.MultilevelCache
dotnet add package Masa.Contrib.Caching.MultilevelCache --version 0.6.0-rc.5
dotnet add package Masa.Contrib.Caching.Distributed.StackExchangeRedis --version 0.6.0-rc.5
Redis
快取,修改Program.cs
var builder = WebApplication.CreateBuilder(args);
//註冊多級快取
builder.Services.AddMultilevelCache(distributedCacheOptions =>
{
distributedCacheOptions.UseStackExchangeRedisCache();//使用分散式Redis快取
});
User
類,用於接收使用者資訊public class User
{
public string Name { get; set; }
public int Age { get; set; }
}
IMultilevelCacheClient
,修改Program.cs
// 設定快取
app.MapPost("/set/{id}", async (IMultilevelCacheClient multilevelCacheClient, [FromRoute] string id, [FromBody] User user) =>
{
await multilevelCacheClient.SetAsync(id, user);
return Results.Accepted();
});
// 獲取快取
app.MapGet("/get/{id}", async (IMultilevelCacheClient multilevelCacheClient, [FromRoute] string id) =>
{
var value = await multilevelCacheClient.GetAsync<User>(id);
return Results.Ok(value);
});
藉助Postman
或者Swagger
或者使用其它API測試工具,分別測試設定快取與獲取快取,以驗證分散式快取以及多級快取是可以正常使用的。
友情提示:檢查Redis快取,找到剛剛你設定的快取,確定下它的儲存結果是否與你想象的一致!!
經過測試,我們的分散式快取與多級快取是可以正常使用的,但檢視Redis的儲存結果後,發現它們實際的儲存與我們心目中的結果好像是有點出入,它們分別是:
快取Key支援三種規則:
列舉 | 值 | 描述 |
---|---|---|
None | 1 | 不做處理,傳入的Key即為實際的快取Key |
TypeName | 2 | 實際的快取Key = $"{GetTypeName(T)}.{傳入快取Key}" (預設) |
TypeAlias | 3 | 根據TypeName得到對應的別名與Key的組合,Format: ${TypeAliasName}{:}{key} |
詳細規則可檢視
Masa.Contrib.Caching.Distributed.StackExchangeRedis使用的是Hash儲存,通過使用Hash儲存,支援快取的絕對過期以及相對過期,其中:
鍵 | 描述 | 詳細 | 特殊 |
---|---|---|---|
absexp | 絕對過期時間的Ticks | 自公曆 0001-01-01 00:00:00:000 到絕對過期時間的計時週期數 (1週期 = 100ns 即 1/10000 ms) |
-1 為永不過期 |
sldexp | 滑動過期時間的Ticks | 自公曆 0001-01-01 00:00:00:000 到滑動過期時間的計時週期數 (1週期 = 100ns 即 1/10000 ms,每次獲取資料時會重新整理滑動過期時間) |
-1 為永不過期 |
data | 資料 | 儲存使用者設定的快取資料 |
方案一. 通過本地組態檔註冊
appsettings.json
檔案{
"RedisConfig":{
"Servers":[
{
"Host":"localhost",
"Port":6379
}
],
"DefaultDatabase":3,
"ConnectionPoolSize":10
}
}
builder.Services.AddDistributedCache(distributedCacheOptions =>
{
distributedCacheOptions.UseStackExchangeRedisCache();
});
方案二. 手動指定Redis設定註冊
builder.Services.AddDistributedCache(distributedCacheOptions =>
{
distributedCacheOptions.UseStackExchangeRedisCache(options =>
{
options.Servers = new List<RedisServerOptions>()
{
new("localhost", 6379)
};
options.DefaultDatabase = 3;
options.ConnectionPoolSize = 10;
options.GlobalCacheOptions = new CacheOptions()
{
CacheKeyType = CacheKeyType.None //全域性禁用快取Key格式化處理
};
});
});
方案三. 通過選項模式註冊
builder.Services.Configure<RedisConfigurationOptions>(redisConfigurationOptions =>
{
redisConfigurationOptions.Servers = new List<RedisServerOptions>()
{
new("localhost", 6379)
};
redisConfigurationOptions.DefaultDatabase = 3;
redisConfigurationOptions.ConnectionPoolSize = 10;
redisConfigurationOptions.GlobalCacheOptions = new CacheOptions()
{
CacheKeyType = CacheKeyType.None
};
});
builder.Services.AddDistributedCache(distributedCacheOptions =>
{
distributedCacheOptions.UseStackExchangeRedisCache();
});
方案四. 通過指定Configuration
註冊
appsettings.json
檔案{
"RedisConfig":{
"Servers":[
{
"Host": "localhost",
"Port": 6379
}
],
"DefaultDatabase": 3,
"ConnectionPoolSize": 10
}
}
Configuration
註冊分散式Redis快取var builder = WebApplication.CreateBuilder(args);
//註冊分散式快取
builder.Services.AddDistributedCache(distributedCacheOptions =>
{
// 使用儲存Redis設定的Configuration
distributedCacheOptions.UseStackExchangeRedisCache(builder.Configuration.GetSection("RedisConfig"));
});
方案五. 將設定儲存到Dcc上,並通過Configuration提供的手動對映功能,實現選項模式
builder.AddMasaConfiguration(configurationBuilder =>
{
configurationBuilder.UseDcc();//使用Dcc 擴充套件Configuration能力,支援遠端設定
configurationBuilder.UseMasaOptions(options =>
{
//通過手動對映RedisConfigurationOptions的設定,實現選項模式
options.MappingConfigurationApi<RedisConfigurationOptions>("{替換為Dcc中設定所屬的AppId}", "{替換為Redis設定的物件名稱}");
});
});
builder.Services.AddDistributedCache(distributedCacheOptions =>
{
distributedCacheOptions.UseStackExchangeRedisCache();
});
方案三、四、五的本質都是通過支援選項模式來註冊分散式Redis快取
修改快取Key對映規則十分簡單,我們在設定時更改CacheKeyType為對應的規則即可,但當 CacheKeyType = 3 需要注意,它需要額外提供型別名與別名的對應關係,完整例子如下:
appsettings.json
, 將CacheKeyType的值改為 3{
"RedisConfig":{
"Servers":[
{
"Host":"localhost",
"Port":6379
}
],
"DefaultDatabase":3,
"ConnectionPoolSize":10,
"GlobalCacheOptions": {
"CacheKeyType": 3 //CacheKeyType為3時啟用別名格式化快取Key,可節省快取Key的鍵長度
}
}
}
builder.Services.AddDistributedCache(distributedCacheOptions =>
{
distributedCacheOptions.UseStackExchangeRedisCache();
}, typeAliasOptions =>
{
typeAliasOptions.GetAllTypeAliasFunc = () => new Dictionary<string, string>()
{
{ "String", "s" }//當型別為String時,格式化後的Key為 s:key
};
});
通過指定型別與別名的對應關係,從而使得最終形成較短的快取Key,以達到節省儲存空間的目的,快取Key生成規則可檢視
方案一. 通過本地組態檔註冊
appsettings.json
檔案,分別設定多級快取設定以及Redis快取設定{
// 多級快取全域性設定,非必填
"MultilevelCache": {
"SubscribeKeyPrefix": "masa",//預設訂閱方key字首,用於拼接channel
"SubscribeKeyType": 3, //預設訂閱方key的型別,預設ValueTypeFullNameAndKey,用於拼接channel
"CacheEntryOptions": {
"AbsoluteExpirationRelativeToNow": "00:00:30",//絕對過期時長(距當前時間)
"SlidingExpiration": "00:00:50"//滑動過期時長(距當前時間)
}
},
// Redis分散式快取設定
"RedisConfig": {
"Servers": [
{
"Host": "localhost",
"Port": 6379
}
],
"DefaultDatabase": 3
}
}
builder.Services.AddMultilevelCache(distributedCacheOptions =>
{
distributedCacheOptions.UseStackExchangeRedisCache();
});
方案二. 通過手動指定設定
builder.Services.AddMultilevelCache(distributedCacheOptions =>
{
distributedCacheOptions.UseStackExchangeRedisCache(RedisConfigurationOptions);
});
未設定記憶體快取時,預設記憶體快取永久有效
除了上述兩種方式以外,多級快取的記憶體快取設定也同樣支援選項模式,我們可以通過Dcc或者利用 builder.Services.Configure<MultilevelCacheOptions>(builder.Configuration)
來支援選項模式
IDistributedCacheClient
介面提供以下方法來處理分散式快取
以下方法會根據全域性快取Key的規則設定以及傳入快取Key的規則設定,檢測是否需要格式化快取Key,對需要格式化Key的操作按照快取Key格式化規則進行處理,詳細檢視:
Get<T>
、GetAsync<T>
: 根據快取Key返回型別為T
的結果 (如果快取不存在,則返回Null)GetList<T>
、GetListAsync<T>
: 根據快取Key集合返回對應的快取值的集合 (針對不存在的快取key,其值返回Null)GetOrSet<T>
、GetOrSetAsync<T>
: 如果在快取中找到,則返回型別為T
的結果,如果快取未找到,則執行Setter
,並返回Setter
的結果Set<T>
、SetAsync<T>
: 將指定的快取Key以及快取值新增到快取SetList<T>
、SetListAsync<T>
: 將指定的快取Key、Value集合新增快取Remove<T>
、RemoveAsync<T>
: 將指定的快取Key (快取Key集合) 從快取中移除Refresh<T>
、RefreshAsync<T>
: 重新整理指定的快取Key (快取Key集合) 的生命週期
Exists<T>
、ExistsAsync<T>
: 如果在快取中找到,則返回true,否則返回falseGetKeys<T>
、GetKeysAsync<T>
: 根據key pattern 得到符合規則的所有快取KeyGetByKeyPattern<T>
、GetByKeyPatternAsync<T>
: 根據key pattern 得到符合規則的所有快取Key、Value集合HashIncrementAsync
: 將指定的快取Key的值增加Value,並返回增長後的結果HashDecrementAsync
: 將指定的快取Key的值減少Value,並返回減少後的結果
KeyExpire<T>
、KeyExpireAsync<T>
: 設定快取Key的生命週期以下方法不執行快取Key格式化, 應傳入快取完整Key:
Remove
、RemoveAsync
: 將指定的快取Key (快取Key集合) 從快取中移除Refresh
、RefreshAsync
: 重新整理指定的快取Key (快取Key集合) 的生命週期
Exists
、ExistsAsync
: 如果在快取中找到,則返回true,否則返回falseGetKeys
、GetKeysAsync
: 根據key pattern 得到符合規則的所有快取Key
KeyExpire
、KeyExpireAsync
: 設定快取Key的生命週期Get<T>
、GetAsync<T>
: 根據快取Key返回型別為T
的結果 (如果快取不存在,則返回Null) (支援監控快取變更)GetList<T>
、GetListAsync<T>
: 根據快取Key集合返回對應的快取值的集合 (針對不存在的快取key,其值返回Null)GetOrSet<T>
、GetOrSetAsync<T>
: 如果在快取中找到,則返回型別為T
的結果,如果快取未找到,則執行Setter
,並返回Setter
的結果Set<T>
、SetAsync<T>
: 將指定的快取Key以及快取值新增到快取SetList<T>
、SetListAsync<T>
: 將指定的快取Key、Value集合新增快取Remove<T>
、RemoveAsync<T>
: 將指定的快取Key (快取Key集合) 從快取中移除Refresh<T>
、RefreshAsync<T>
: 重新整理指定的快取Key (快取Key集合) 的生命週期
如果Name為空字串時,可直接使用
IDistributedCacheClient
或IMultilevelCacheClient
, 預設註冊不指定Name時,則其Name為空字串,可不通過Factory建立
Masa Framework
提供了分散式快取以及多級快取的實現,其中有幾個優秀的功能:
Client.Get<User>("1")
,而無需:Client.Get<User>("User.1")
Assignment16
https://github.com/zhenlei520/MasaFramework.Practice
MASA.Framework:https://github.com/masastack/MASA.Framework
MASA.EShop:https://github.com/masalabs/MASA.EShop
MASA.Blazor:https://github.com/BlazorComponent/MASA.Blazor
如果你對我們的 MASA Framework 感興趣,無論是程式碼貢獻、使用、提 Issue,歡迎聯絡我們
本文來自部落格園,作者:磊_磊,轉載請註明原文連結:https://www.cnblogs.com/zhenlei520/p/16813952.html
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連結,否則保留追究法律責任的權利