九、.net core(.NET 6)添加通用的Redis功能


 .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是別名,可以任意起。IpRedis的服務端地址,例如安裝本地,就是127.0.0.1,端口號Port默認是6379,密碼可以通過Redis安裝的根目錄下的配置文件進行設置,Timeout是連接的超時時間,Db是使用RedisDB區,一般RedisDB區默認是015。注意:此處的配置使用的是數組,用於將來進行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;
            }

        }
View Code

 

然后,新建一個方法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;
        }
View Code

 

在構造函數里面,進行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();
    }
View Code

接口實現部分的整體源碼:

  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));
        }

    }
View Code

 

由於時間關系,就不一一列舉各自的功能了,各位大佬們可以自行嘗試。

最后,說個小竅門:Key值如果使用冒號,在客戶端上面查看就會自動變成分層結構。舉個例子,改寫控制器,原本設置的Test這個Key,改寫為Test:Wesky:

 

 

然后,啟動程序,讓他執行一下,用於生成一條記錄,例如此處我寫入:Hello Key’s Rules:

 

 

由此可見,Key值分層顯示了。在一些場合下,可以使用冒號來分隔開不同層級的Key,以便於在客戶端查看。

至此,結束,歡迎打賞、評論和點贊。

版權所有,轉載請注明出處:https://www.cnblogs.com/weskynet/p/14847526.html

備注:如果有需要Redis、以及Redis安裝包的,以及安裝教程,可以加以下的QQ群進行獲取和咨詢。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM