一、前言
Redis的介紹網上很多不再贅述。本次環境為net core 2.2,使用的StackExchange.Redis來操作Redis。以前的StackExchange.Redis存在連接超時的情況,現在使用最新版本並全部使用異步方法可以解決。
二、引用Microsoft.Extensions.Caching.StackExchangeRedis
通過nuget搜索Microsoft.Extensions.Caching.StackExchangeRedis安裝,因為依賴項版本的問題我這里用的版本是2.2.5,其本質上也是封裝的StackExchange.Redis,但是它實現了net core規定的IDistributedCache接口。
三、添加redis服務
在Startup.cs中的ConfigureServices中添加Redis的服務,會自動進行依賴注入。最簡單的如下:
public void ConfigureServices(IServiceCollection services) {//...... //添加redis連接 services.AddStackExchangeRedisCache(options => { options.Configuration = "127.0.0.1:6379"; options.InstanceName = "SampleInstance"; }); //...... }
InstaceName:實例名,加在redis的key前面的。
Configuration:連接redis的鏈接。
還存在一個優先級更高的ConfigurationOptions,可以配置多個redis服務的連接、密碼等。
public void ConfigureServices(IServiceCollection services) {//..... //添加redis連接 services.AddStackExchangeRedisCache(options => { options.ConfigurationOptions = new ConfigurationOptions() { EndPoints = { { "127.0.0.1", 6379 } }, //Password = "123456" }; }); //...... }
具體的屬性如下:
配置選項 |
默認 | 含義 |
---|---|---|
AbortOnConnectFail |
true (false 在Azure上) |
如果為true,Connect 則在沒有服務器可用時將不會創建連接 |
AllowAdmin |
false |
啟用一系列被認為具有風險的命令 |
ChannelPrefix |
null |
所有發布/訂閱操作的可選通道前綴 |
ConnectRetry |
3 |
初始期間重復嘗試連接的次數 Connect |
ConnectTimeout |
5000 |
連接操作超時(毫秒) |
ConfigurationChannel |
__Booksleeve_MasterChanged |
用於傳達配置更改的廣播頻道名稱 |
ConfigCheckSeconds |
60 |
檢查配置的時間(秒)。如果支持,它可以充當交互式套接字的保持活動狀態。 |
DefaultDatabase |
null |
默認數據庫索引,從0 到databases - 1 |
KeepAlive |
-1 |
發送消息以幫助套接字保持活動的時間(秒)(默認為60秒) |
ClientName |
null |
標識Redis中的連接 |
Password |
null |
Redis服務器密碼 |
Proxy |
Proxy.None |
使用中的代理類型(如果有);例如“ twemproxy” |
ResolveDns |
false |
指定DNS解析應該是明確且渴望的,而不是隱式的 |
ResponseTimeout |
SyncTimeout |
決定套接字是否不健康的時間(毫秒) |
Ssl |
false |
指定應使用SSL加密 |
SslHost |
null |
在服務器的證書上強制使用特定的SSL主機身份 |
SslProtocols |
null |
使用加密連接時支持Ssl / Tls版本。使用“ |” 提供多個值。 |
SyncTimeout |
5000 |
允許同步操作的時間(毫秒) |
TieBreaker |
__Booksleeve_TieBreak |
在模棱兩可的主方案中用於選擇服務器的密鑰 |
DefaultVersion |
(3.0 在Azure中,否則2.0 ) |
Redis版本級別(在服務器不可用時有用) |
WriteBuffer |
4096 |
輸出緩沖區的大小 |
四、操作Redis
在控制器中通過構造函數依賴注入獲取redis連接對象。
public class HomeController : Controller { private readonly IDistributedCache cache; public HomeController(IDistributedCache _cache) { this.cache = _cache; } }
由於是實現了IDistributedCache規定的接口Get、Set、Remove、Refresh等。
所以設置緩存(有則更新,無則新增)、獲取緩存、刷新緩存(不是刷新值是刷新過期時間)和刪除緩存的代碼如下。
//編輯緩存 cache.SetString(key, value); //獲取緩存 var values = cache.GetString(key); //更新緩存過期時間 cache.RefreshAsync(key); //刪除緩存 cache.RemoveAsync(key);
如果想設置緩存過期時間則通過DistributedCacheEntryOptions,它可以設置滑動過期時間(SlidingExpiration)、絕對過期時間(AbsoluteExpiration)和相對於現在的絕對過期時間(AbsoluteExpirationRelativeToNow)。
var options = new DistributedCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromSeconds(20)); cache.SetString(key, value, options);
通過redis的可視化工具Redis Desktop Manager可以看到緩存存儲在一號庫為hash類型,有我們存儲的值、滑動過期時間和絕對過期時間。不過獲取到的數據為string。
五、使用StackExchange.Redis
上面的代碼存在一個問題,就是IDistributedCache之后對緩存的存儲默認為其規定格式的hash類型,雖然我們獲取到的數據為string。這樣我們想操作list、set等其他類型就不行了,並且不能指定庫進行存儲。所以為了更加靈活這時候就要直接用StackExchange.Redis。
因為引用Microsoft.Extensions.Caching.StackExchangeRedis的時候已經帶上了StackExchange.Redis.dll的依賴項,所以不用再引用了,否則在nuget中搜索StackExchange.Redis進行引用。
1.基本使用
StackExchange.Redis 中核心對象是在 StackExchange.Redis 命名空間中的 ConnectionMultiplexer 類,這個對象隱藏了多個服務器的詳細信息。 因為 ConnectionMultiplexer 要做很多事,所以它被設計為在調用者之間可以共享和重用,不需要在執行每一個操作的時候就創建一個 ConnectionMultiplexer ,它完全是線程安全的。 但現在,讓我們來先創建一個ConnectionMultiplexer 類的實例保存以重用。 使用 ConnectionMultiplexer.Connect 或 ConnectionMultiplexer.ConnectAsync方法,傳遞配置字符串或ConfigurationOptions 對象(同上面提到過的)。 配置字符串可以采用逗號分隔的一系列節點的形式訪問多個服務,所以讓我們在默認端口(6379)上連接到本地機器上的一個實例:
private static ConnectionMultiplexer redisConnection { get; } static RedisCache() { redisConnection = ConnectionMultiplexer.Connect("127.0.0.1:6379"); }
ConnectionMultiplexer實現了IDisposable接口而且可以在不再需要的時候處理釋放掉。
2.使用Redis
訪問Redis使用上述獲取的連接對象:
IDatabase db = redisConnection.GetDatabase(0);
用GetDatabase()返回的對象成本很低,不需要特殊存儲。可以傳入redis數據庫的號碼,使用指定數據庫,上面的例子就是使用0號數據庫。
擁有了IDatabase就可以調用方法去操作redis,所有的方法都有同步和異步兩套,命名和微軟要求的一樣。
下面簡單的對五種數據類型進行基礎操作:
(1)String字符串
添加
await redisConnection.GetDatabase().StringSetAsync(key, value, TimeSpan.FromSeconds(20));
獲取
await redisConnection.GetDatabase().StringGetAsync(key);
(2)List列表
從列表底部和頂部插入
//底部插入 await redisConnection.GetDatabase().ListRightPushAsync(key, value); //頂部插入 await redisConnection.GetDatabase().ListLeftPushAsync(key, value);
從列表底部和頂部獲取一個數據
//底部獲取一個 await redisConnection.GetDatabase().ListRightPopAsync(key); //頂部獲取一個 await redisConnection.GetDatabase().ListLeftPopAsync(key);
(3)Hash哈希
添加
await redisConnection.GetDatabase().HashSetAsync(key, primaryKey, value1); await redisConnection.GetDatabase().HashSetAsync(key, primaryKey, value2);
獲取
await redisConnection.GetDatabase().HashGetAsync(key, primaryKey);
(4)Set集合
添加
await redisConnection.GetDatabase().SetAddAsync(key, value);
獲取並集
await redisConnection.GetDatabase().SetCombine(SetOperation.Union, key1, key2);
(5)Sorted Set有序集合
添加
await redisConnection.GetDatabase().SortedSetAdd(key, value, sort);