封裝redis方法


最近在自己的項目有使用到redis,一直使用別人封裝的東西,今天想自己動手封裝一下,順便深入了解redis。

安裝

我使用的StackExchange.Redis

GitHub:https://github.com/StackExchange/StackExchange.Redis/

安裝最新版本就行

封裝

官網有這樣一句話

The central object in StackExchange.Redis is the ConnectionMultiplexer class in the StackExchange.Redis namespace; this is the object that hides away the details of multiple servers. Because the ConnectionMultiplexer does a lot, it is designed to be shared and reused between callers. You should not create a ConnectionMultiplexer per operation. It is fully thread-safe and ready for this usage. In all the subsequent examples it will be assumed that you have a ConnectionMultiplexer instance stored away for re-use. 

通過百度翻譯

中心對象StackExchange.Redis中的ConnectionMultiplexer類StackExchange.Redis名稱空間;這是隱藏多個服務器詳細信息的對象。因為ConnectionMultiplexer做了很多事情,所以它被設計成在調用者之間共享和重用。不應為每個操作創建ConnectionMultiplexer。它是完全線程安全的,可以使用它。在后面的所有示例中,我們將假定您有一個ConnectionMultiplexer實例存儲起來以供重用。

那我可以封裝一個Redis連接類,這個類型可以單例模式封裝成一個單例。

 public class RedisConnectionHelper
    {
        /// <summary>
        /// 連接redis server 類
        /// </summary>
        public static ConnectionMultiplexer _connection;
        public readonly static object _locker = new object();

        /// <summary>
        /// 緩存連接實例
        /// </summary>
        public static readonly Dictionary<string, ConnectionMultiplexer> _connectionCache =
            new Dictionary<string, ConnectionMultiplexer>();
        /// <summary>
        /// 連接實例  (單例模式)
        /// </summary>
        public static ConnectionMultiplexer Instance
        {

            get
            {

                if (_connection == null)
                {
                    lock (_locker)
                    {
                        if (_connection == null || !_connection.IsConnected)
                        {
                            _connection = CreateConnection();
                        }
                    }
                }
                return _connection;
            }
        }
        /// <summary>
        /// https://stackexchange.github.io/StackExchange.Redis/Basics
        /// </summary>
        /// <param name="connectionString"></param>
        public static ConnectionMultiplexer CreateConnection(string connectionString = null)
        {
            //連接字符串
            string connectStr = connectionString ?? "127.0.0.1:6379";
            ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(connectStr);
            //redis 事件注冊
            redis.ConnectionFailed += Redis_ConnectionFailed;
            return redis;
        }

        public static ConnectionMultiplexer GetConnectionMultiplexer(string connectionString)
        {
            if (!_connectionCache.ContainsKey(connectionString))
            {
                _connectionCache[connectionString] = CreateConnection(connectionString);
            }
            return _connectionCache[connectionString];
        }
        /// <summary>
        /// redis 服務連接失敗事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void Redis_ConnectionFailed(object sender, ConnectionFailedEventArgs e)
        {
            Console.WriteLine(e.Exception);
        }
    }

實例化ConnectionMultiplexer對象之后,可以直接GetDatabase獲取到Redis數據庫對象(IDatabase類型)。

這其中有很多操作數據的方法,我每次在實例化Db之后再去調用方法,有點麻煩,再封裝一個方法類,需要注意的是這里封裝方法需要安裝Newtonsoft.Json

這里為什么需要用到這跟呢,因為很多情況下,如果我需要緩存一個對象的時候,例如一個Student,那么這種情況下,Redis是沒法直接存的,需要先Json化為string類型

然后再保存。

這里重點要注意的是操作list的方法,redis中的list是一個雙向鏈表,list集合可以左右、中間插入元素。所以在這里在封裝的時候還是有一些坑去爬的。

public static class RedisHelper
    {
        public static readonly ConnectionMultiplexer _connectin;
        /// <summary>
        /// 數據庫id
        /// </summary>
        public static int DbNum { get; set; }
        /// <summary>
        /// 連接方式
        /// </summary>
        public static string ConnectionString { get; set; }

        static RedisHelper()
        {
            DbNum = -1;
            ConnectionString = null;
            _connectin = string.IsNullOrEmpty(ConnectionString) ?
                   RedisConnectionHelper.Instance :
                   RedisConnectionHelper.GetConnectionMultiplexer(ConnectionString);
        }
        /// <summary>
        /// 獲取db
        /// </summary>
        public static IDatabase Db
        {
            get
            {
                return _connectin.GetDatabase(DbNum);
            }
        }
        /// <summary>
        /// 執行委托
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="func"></param>
        /// <returns></returns>
        public static T Do<T>(Func<IDatabase, T> func)
        {
            return func(Db);
        }
        #region string
        /// <summary>
        /// 保存string
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expiry"></param>
        public static bool StringSet(string key, string value, TimeSpan? expiry = null)
        {
            return Do(d => d.StringSet(key, value,expiry));
        }

        /// <summary>
        /// 異步保存
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expiry"></param>
        /// <returns></returns>
        public static async Task<bool> StringSetAsync(string key, string value, TimeSpan? expiry = null)
        {
            return await Do(d => d.StringSetAsync(key, value, expiry));
        }
        /// <summary>
        /// 獲取值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string StringGet(string key)
        {
            return Do(d => d.StringGet(key));
        }

        /// <summary>
        /// 獲取值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static async Task<string> StringGetAsync(string key)
        {
            return await Do(d => d.StringGetAsync(key));
        }
        /// <summary>
        /// 刪除鍵
        /// </summary>
        /// <param name="key"></param>
        public static bool KeyDelete(string key)
        {
            return Do(d => d.KeyDelete(key));
        }

        /// <summary>
        /// 刪除鍵
        /// </summary>
        /// <param name="key"></param>
        public static async Task<bool> KeyDeleteAsync(string key)
        {
            return await Do(d => d.KeyDeleteAsync(key));
        }
        /// <summary>
        /// set
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expiry"></param>
        /// <returns></returns>
        public static bool StringSet<T>(string key, T value, TimeSpan? expiry = null)
        {
            string json = Serialize(value);
            return Do(d => d.StringSet(key, json, expiry));
        }

        /// <summary>
        /// set
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expiry"></param>
        /// <returns></returns>
        public static async Task<bool> StringSetAsync<T>(string key, T value, TimeSpan? expiry = null)
        {
            string json = Serialize(value);
            return await Do(d => d.StringSetAsync(key, json, expiry));
        }
        /// <summary>
        /// get 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expiry"></param>
        /// <returns></returns>
        public static T StringGet<T>(string key)
        {
            string json = Do(d => d.StringGet(key)).ToString();
            return Deserialize<T>(json);
        }

        /// <summary>
        /// get 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expiry"></param>
        /// <returns></returns>
        public static async Task<T> StringGetAsync<T>(string key)
        {
            string json = await Do(d => d.StringGetAsync(key));
            return Deserialize<T>(json);
        }
        #endregion
        /// <summary>
        /// 序列化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <returns></returns>
        private static string Serialize<T>(T value)
        {
            var result = value is string ? value.ToString() : JsonConvert.SerializeObject(value,
                new JsonSerializerSettings
                {
                    DateFormatString = "yyyy-MM-dd hh:mm:ss"
                });
            return result;
        }
        /// <summary>
        /// 解析
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="json"></param>
        /// <returns></returns>
        private static T Deserialize<T>(string json)
        {
            if (string.IsNullOrEmpty(json)) return default;
            return JsonConvert.DeserializeObject<T>(json);
        }
        /// <summary>
        /// 解析redis緩存的集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="values"></param>
        /// <returns></returns>
        private static List<T> DeserializeList<T>(RedisValue[] values)
        {
            return values.Select(s => Deserialize<T>(s)).ToList();
        }

        #region List
        /// <summary>
        /// 保存list 集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void SetList<T>(string key, List<T> value)
        {
            if (value.Count > 0)
            {
                var values = value.Select(s => (RedisValue)Serialize(s)).ToArray();
                Do(d => d.ListRightPush(key, values));
            }
        }

        /// <summary>
        /// 保存list 集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static async Task SetListAsync<T>(string key, List<T> value)
        {
            if (value.Count > 0)
            {
                var values = value.Select(s => (RedisValue)Serialize(s)).ToArray();
                await Do(d => d.ListRightPushAsync(key, values));
            }
        }
        /// <summary>
        /// 獲取list 集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public static List<T> GetList<T>(string key)
        {
            var values = Do(d => d.ListRange(key));
            if (values.IsNullOrEmpty())
            {
                return values.Select(s => Deserialize<T>(s)).ToList();
            }
            return default;
        }
        /// <summary>
        /// 獲取list 集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public static async Task<List<T>> GetListAsync<T>(string key)
        {
            var values = await Do(d => d.ListRangeAsync(key));
            if (values.IsNullOrEmpty())
            {
                return values.Select(s => Deserialize<T>(s)).ToList();
            }
            return default;
        }
        /// <summary>
        /// 刪除並返回集合的第一個元素
        /// ListLeftPop
        /// </summary>
        /// <param name="key"></param>
        public static T RemoveFirst<T>(string key)
        {
            var json = Do(d => d.ListLeftPop(key));
            return Deserialize<T>(json);
        }
        /// <summary>
        /// 刪除並返回集合的第一個元素
        /// ListLeftPop
        /// </summary>
        /// <param name="key"></param>
        public static async Task<T> RemoveFirstAsync<T>(string key)
        {
            var json = await Do(d => d.ListLeftPopAsync(key));
            return Deserialize<T>(json);
        }
        /// <summary>
        /// 刪除並返回集合的最后一個元素
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public static T RemoveLast<T>(string key)
        {
            return Deserialize<T>(Do(d => d.ListRightPop(key)));
        }

        /// <summary>
        /// 刪除並返回集合的最后一個元素
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public static async Task<T> RemoveLastAsync<T>(string key)
        {
            return Deserialize<T>(await Do(d => d.ListRightPopAsync(key)));
        }
        /// <summary>
        /// 根據索引獲取集合 (默認所有)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="start"></param>
        /// <param name="stop"></param>
        /// <returns></returns>
        public static List<T> ListRange<T>(string key, long start = 0, long stop = -1)
        {
            var json = Do(d => d.ListRange(key, start, stop));
            return DeserializeList<T>(json);
        }

        /// <summary>
        /// 根據索引獲取集合 (默認所有)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="start"></param>
        /// <param name="stop"></param>
        /// <returns></returns>
        public static async Task<List<T>> ListRangeAsync<T>(string key, long start = 0, long stop = -1)
        {
            var json = await Do(d => d.ListRangeAsync(key, start, stop));
            return DeserializeList<T>(json);
        }

        /// <summary>
        /// 根據元素刪除
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns>返回刪除元素數量</returns>
        public static int RemoveAt<T>(string key,T value)
        {
            return (int)Do(d => d.ListRemove(key, Serialize(value)));
        }

        /// <summary>
        /// 根據元素刪除
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns>返回刪除元素數量</returns>
        public static async Task<int> RemoveAtAsync<T>(string key, T value)
        {
            return (int)await Do(d => d.ListRemoveAsync(key, Serialize(value)));
        }
        /// <summary>
        /// 向集合開頭添加一個元素
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void AddFirst<T>(string key, T value)
        {
            Do(d => d.ListLeftPush(key, Serialize(value)));
        }
        /// <summary>
        /// 向集合開頭添加一個元素
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static async Task AddFirstAsync<T>(string key, T value)
        {
            await Do(d => d.ListLeftPushAsync(key, Serialize(value)));
        }
        /// <summary>
        /// 向集合末尾添加一個元素
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void AddLast<T>(string key, T value)
        {
            Do(d => d.ListRightPush(key, Serialize(value)));
        }
        /// <summary>
        /// 向集合末尾添加一個元素
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>

        public static async Task AddLastAsync<T>(string key, T value)
        {
            await Do(d => d.ListRightPushAsync(key, Serialize(value)));
        }
        /// <summary>
        /// 判斷對象是否存在
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool Contains<T>(string key, T value)
        {
            //數量
            var length = Count(key);
            //格式話對象
            var json = Serialize(value);
            for (int i = 0; i < length; i++)
            {
                if (Do(d => d.ListGetByIndex(key, i).ToString().Equals(json)))
                {
                    return true;
                }
            }
            return false;
        }
        /// <summary>
        /// 判斷對象是否存在
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static async Task<bool> ContainsAsync<T>(string key, T value)
        {
            //數量
            var length = await CountAsync(key);
            //格式話對象
            var json = Serialize(value);
            for (int i = 0; i < length; i++)
            {
                var item = await Do(d => d.ListGetByIndexAsync(key, i));
                if (item.ToString().Equals(json))
                {
                    return true;
                }
            }
            return false;
        }
        /// <summary>
        /// 根據索引獲取對象
        /// ListGetByIndex
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        public static T Get<T>(string key, int index)
        {
            string json = Do(d => d.ListGetByIndex(key, index));
            return Deserialize<T>(json);
        }

        /// <summary>
        /// 根據索引獲取對象
        /// ListGetByIndex
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        public static async Task<T> GetAsync<T>(string key, int index)
        {
            string json = await Do(d => d.ListGetByIndexAsync(key, index));
            return Deserialize<T>(json);
        }
        /// <summary>
        /// 根據對象獲取索引
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static int IndexOf<T>(string key, T value)
        {
            //數量
            var length = Count(key);
            //格式話對象
            var json = Serialize(value);
            for (int i = 0; i < length; i++)
            {
                if ( Do(d => d.ListGetByIndex(key, i).ToString().Equals(json)))
                {
                    return i;
                }
            }
            return -1;
        }

        /// <summary>
        /// 根據對象獲取索引
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static async Task<int> IndexOfAsync<T>(string key, T value)
        {
            //數量
            var length = await CountAsync(key);
            //格式話對象
            var json = Serialize(value);
            for (int i = 0; i < length; i++)
            {
                var item = await Do(d => d.ListGetByIndexAsync(key, i));
                if ( item.ToString().Equals(json))
                {
                    return i;
                }
            }
            return -1;
        }
        /// <summary>
        /// 獲取list的數量
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static int Count(string key)
        {
            return (int)Do(d => d.ListLength(key));
        }

        /// <summary>
        /// 獲取list的數量
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static async Task<int> CountAsync(string key)
        {
            return (int)await Do(d => d.ListLengthAsync(key));
        }
        #endregion
    }

總結

很多東西需要自己動手去試試才能獲得更多知識。

 封裝GitHub:https://github.com/QQ2287991080/Zero.Core/tree/master/src/Zero.Core.Common/Redis

測試GitHub:https://github.com/QQ2287991080/Zero.Core/blob/master/src/Zero.Core.xUnitTest/Redis/RedisTest.cs


免責聲明!

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



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