.net core 編寫通用的Redis功能
在 Package項目里面,添加包:StackExchange.Redis:
在Common工具文件夾下,新建 Wsk.Core.Redis類庫項目,並新建 RedisManage 類和對應接口 IRedisManage,如下圖。然后,在該項目里面,引用共用包項目Wsk.Core.Package,用以使用Redis有關功能。
在RedisManage類里面,新增幾個用於連接Redis配置的全局變量,以及一個構造函數:
在配置文件里面,新建Redis的有關配置信息:
配置的Json文本:
"Redis": [ { "Name": "Wesky", "Ip": "127.0.0.1", "Port": 6379, "Password": "wesky123", "Timeout": 30, "Db": 3 } ]
其中,Name是別名,可以任意起。Ip是Redis的服務端地址,例如安裝本地,就是127.0.0.1,端口號Port默認是6379,密碼可以通過Redis安裝的根目錄下的配置文件進行設置,Timeout是連接的超時時間,Db是使用Redis的DB區,一般Redis的DB區默認是0到15。注意:此處的配置使用的是數組,用於將來進行Redis分布式操作的可拓展。
看下redis安裝目錄下的配置文件局部一覽:
如果打算修改該配置文件來實現修改有關的配置信息,但是沒有效果,注意在windows服務里面把redis服務進行重新啟動。如果還不行,就把另外一個conf配置文件也做同樣的操作,然后再重啟redis服務。
接着,在解決方案下,新建一個文件夾,叫DataEntities,該文件夾當做將來存放各種實體類或有關項目的目錄。現在咱們在該新建的文件夾下,新建一個類庫項目:Wsk.Core.Entity,然后新建一個實體類,叫RedisConfig,用於讀取到配置文件的Redis信息進行賦值使用:
回到Redis類庫項目,在RedisManage類里面,添加一個方法ReadRedisSetting,用於讀取該配置信息,並賦值給ConfigurationOptions類:
ReadRedisSetting代碼:

private ConfigurationOptions ReadRedisSetting() { try { List<RedisConfig> config = AppHelper.ReadAppSettings<RedisConfig>(new string[] { "Redis" }); // 讀取Redis配置信息 if (config.Any()) { ConfigurationOptions options = new ConfigurationOptions { EndPoints = { { config.FirstOrDefault().Ip, config.FirstOrDefault().Port } }, ClientName = config.FirstOrDefault().Name, Password = config.FirstOrDefault().Password, ConnectTimeout = config.FirstOrDefault().Timeout, DefaultDatabase = config.FirstOrDefault().Db, }; return options; } return null; } catch(Exception ex) { _logger.LogError($"獲取Redis配置信息失敗:{ex.Message}"); return null; } }
然后,新建一個方法ConnectionRedis,用於連接Redis:
方法代碼:

private ConnectionMultiplexer ConnectionRedis() { if (this._redisConnection != null && this._redisConnection.IsConnected) { return this._redisConnection; // 已有連接,直接使用 } lock (_redisConnectionLock) { if (this._redisConnection != null) { this._redisConnection.Dispose(); // 釋放,重連 } try { this._redisConnection = ConnectionMultiplexer.Connect(_configOptions); } catch (Exception ex) { _logger.LogError($"Redis服務啟動失敗:{ex.Message}"); } } return this._redisConnection; }
在構造函數里面,進行Redis連接的實現:
現在,做個簡單的測試,新建一個Set方法和一個GetValue方法,用於測試效果:
在IRedisMagane接口里面,添加以上有關的接口方法:
現在轉到啟動項目上,啟動項目新增對Wsk.Core.Redis項目的引用,並且在WskService類下面,新增對剛剛新增的Redis管理類的依賴注入的注冊:
現在,在控制器里面,添加有關構造函數的依賴注入,然后做個實踐,驗證下是否成功。
先改寫控制器內容,先設置一對key/value,然后進行讀取並返回:
啟動項目,輸入Hello Redis! ,然后查看返回對應的內容:
我們打開Redis管理客戶端看看,是不是可以看見有這個值:
因為我們配置的是Db = 3,所以在Db3這個地方,可以看見我們的Key,點擊Tesk,即可在右邊窗口看見對應的內容。說明Redis操作成功。
最后,咱們對Redis管理類進行一些其他功能的添加,以及接口方法的添加,用於完善它的功能鏈,包括移除、讀取實體數據、清空、異步操作等。以下截圖為對應的接口方法展示:
接口部分源碼:

public interface IRedisManage { /// <summary> /// 設置一個 鍵值對 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="ts"></param> void Set(string key, object value, TimeSpan ts); /// <summary> /// //獲取 Reids 緩存值 /// </summary> /// <param name="key"></param> /// <returns></returns> string GetValue(string key); /// <summary> /// 獲取序列化值 /// </summary> /// <typeparam name="TEntity"></typeparam> /// <param name="key"></param> /// <returns></returns> TEntity Get<TEntity>(string key); /// <summary> /// 判斷Key是否存在 /// </summary> /// <param name="key"></param> /// <returns></returns> bool Get(string key); /// <summary> /// 移除某個Key和值 /// </summary> /// <param name="key"></param> void Remove(string key); /// <summary> /// 清空Redis /// </summary> void Clear(); /// <summary> /// 異步獲取 Reids 緩存值 /// </summary> /// <param name="key"></param> /// <returns></returns> Task<string> GetValueAsync(string key); /// <summary> /// 異步獲取序列化值 /// </summary> /// <typeparam name="TEntity"></typeparam> /// <param name="key"></param> /// <returns></returns> Task<TEntity> GetAsync<TEntity>(string key); Task SetAsync(string key, object value, TimeSpan cacheTime); Task<bool> GetAsync(string key); /// <summary> /// 異步移除指定的key /// </summary> /// <param name="key"></param> /// <returns></returns> Task RemoveAsync(string key); /// <summary> /// 異步移除模糊查詢到的key /// </summary> /// <param name="key"></param> /// <returns></returns> Task RemoveByKey(string key); /// <summary> /// 異步全部清空 /// </summary> /// <returns></returns> Task ClearAsync(); }
接口實現部分的整體源碼:

public class RedisManage : IRedisManage { public volatile ConnectionMultiplexer _redisConnection; private readonly object _redisConnectionLock = new object(); private readonly ConfigurationOptions _configOptions; private readonly ILogger<RedisManage> _logger; public RedisManage(ILogger<RedisManage> logger) { _logger = logger; ConfigurationOptions options = ReadRedisSetting(); if (options == null) { _logger.LogError("Redis數據庫配置有誤"); } this._configOptions = options; this._redisConnection = ConnectionRedis(); } private ConfigurationOptions ReadRedisSetting() { try { List<RedisConfig> config = AppHelper.ReadAppSettings<RedisConfig>(new string[] { "Redis" }); // 讀取Redis配置信息 if (config.Any()) { ConfigurationOptions options = new ConfigurationOptions { EndPoints = { { config.FirstOrDefault().Ip, config.FirstOrDefault().Port } }, ClientName = config.FirstOrDefault().Name, Password = config.FirstOrDefault().Password, ConnectTimeout = config.FirstOrDefault().Timeout, DefaultDatabase = config.FirstOrDefault().Db, }; return options; } return null; } catch(Exception ex) { _logger.LogError($"獲取Redis配置信息失敗:{ex.Message}"); return null; } } private ConnectionMultiplexer ConnectionRedis() { if (this._redisConnection != null && this._redisConnection.IsConnected) { return this._redisConnection; // 已有連接,直接使用 } lock (_redisConnectionLock) { if (this._redisConnection != null) { this._redisConnection.Dispose(); // 釋放,重連 } try { this._redisConnection = ConnectionMultiplexer.Connect(_configOptions); } catch (Exception ex) { _logger.LogError($"Redis服務啟動失敗:{ex.Message}"); } } return this._redisConnection; } public string GetValue(string key) { return _redisConnection.GetDatabase().StringGet(key); } public void Set(string key, object value, TimeSpan ts) { if (value != null) { _redisConnection.GetDatabase().StringSet(key, JsonConvert.SerializeObject(value), ts); } } public void Clear() { foreach (var endPoint in this.ConnectionRedis().GetEndPoints()) { var server = this.ConnectionRedis().GetServer(endPoint); foreach (var key in server.Keys()) { _redisConnection.GetDatabase().KeyDelete(key); } } } public bool Get(string key) { return _redisConnection.GetDatabase().KeyExists(key); } public TEntity Get<TEntity>(string key) { var value = _redisConnection.GetDatabase().StringGet(key); if (value.HasValue) { //需要用的反序列化,將Redis存儲的Byte[],進行反序列化 return JsonConvert.DeserializeObject<TEntity>(value); } else { return default(TEntity); } } public void Remove(string key) { _redisConnection.GetDatabase().KeyDelete(key); } public bool SetValue(string key, byte[] value) { return _redisConnection.GetDatabase().StringSet(key, value, TimeSpan.FromSeconds(120)); } public async Task ClearAsync() { foreach (var endPoint in this.ConnectionRedis().GetEndPoints()) { var server = this.ConnectionRedis().GetServer(endPoint); foreach (var key in server.Keys()) { await _redisConnection.GetDatabase().KeyDeleteAsync(key); } } } public async Task<bool> GetAsync(string key) { return await _redisConnection.GetDatabase().KeyExistsAsync(key); } public async Task<string> GetValueAsync(string key) { return await _redisConnection.GetDatabase().StringGetAsync(key); } public async Task<TEntity> GetAsync<TEntity>(string key) { var value = await _redisConnection.GetDatabase().StringGetAsync(key); if (value.HasValue) { return JsonConvert.DeserializeObject<TEntity>(value); } else { return default; } } public async Task RemoveAsync(string key) { await _redisConnection.GetDatabase().KeyDeleteAsync(key); } public async Task RemoveByKey(string key) { var redisResult = await _redisConnection.GetDatabase().ScriptEvaluateAsync(LuaScript.Prepare( //模糊查詢: " local res = redis.call('KEYS', @keypattern) " + " return res "), new { @keypattern = key }); if (!redisResult.IsNull) { var keys = (string[])redisResult; foreach (var k in keys) _redisConnection.GetDatabase().KeyDelete(k); } } public async Task SetAsync(string key, object value, TimeSpan cacheTime) { if (value != null) { await _redisConnection.GetDatabase().StringSetAsync(key, JsonConvert.SerializeObject(value), cacheTime); } } public async Task<bool> SetValueAsync(string key, byte[] value) { return await _redisConnection.GetDatabase().StringSetAsync(key, value, TimeSpan.FromSeconds(120)); } }
由於時間關系,就不一一列舉各自的功能了,各位大佬們可以自行嘗試。
最后,說個小竅門:Key值如果使用冒號,在客戶端上面查看就會自動變成分層結構。舉個例子,改寫控制器,原本設置的Test這個Key,改寫為Test:Wesky:
然后,啟動程序,讓他執行一下,用於生成一條記錄,例如此處我寫入:Hello Key’s Rules:
由此可見,Key值分層顯示了。在一些場合下,可以使用冒號來分隔開不同層級的Key,以便於在客戶端查看。
至此,結束,歡迎打賞、評論和點贊。
版權所有,轉載請注明出處:https://www.cnblogs.com/weskynet/p/14847526.html
備注:如果有需要Redis、以及Redis安裝包的,以及安裝教程,可以加以下的QQ群進行獲取和咨詢。