using Masuit.Tools.Core.Config;
using Newtonsoft.Json;
using StackExchange.Redis;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Masuit.Tools.NoSQL
{
    /// 
    /// Redis操作
    /// 
    public class RedisHelper : IDisposable
    {
        private int DbNum { get; }
        private readonly ConnectionMultiplexer _conn;
        /// 
        /// Redis服务器默认连接字符串,默认为:127.0.0.1:6379,allowadmin=true
        /// 
        internal static string RedisConnectionString { get; set; } = CoreConfig.Configuration["Redis"] ?? "127.0.0.1:6379,allowadmin=true";
        /// 
        /// 自定义键
        /// 
        public string CustomKey;
        /// 
        /// 连接失败 , 如果重新连接成功你将不会收到这个通知
        /// 
        public event EventHandler ConnectionFailed;
        /// 
        /// 重新建立连接之前的错误
        /// 
        public event EventHandler ConnectionRestored;
        /// 
        /// 发生错误时
        /// 
        public event EventHandler ErrorMessage;
        /// 
        /// 配置更改时
        /// 
        public event EventHandler ConfigurationChanged;
        /// 
        /// 更改集群时
        /// 
        public event EventHandler HashSlotMoved;
        /// 
        /// redis类库错误时
        /// 
        public event EventHandler InternalError;
        /// 
        /// 静态连接池
        /// 
        private static ConcurrentDictionary ConnectionCache { get; set; } = new ConcurrentDictionary();
        #region 构造函数
        /// 
        /// 构造函数,使用该构造函数需要先在config中配置链接字符串,连接字符串在config配置文件中的ConnectionStrings节下配置,name固定为RedisHosts,值的格式:127.0.0.1:6379,allowadmin=true,若未正确配置,将按默认值“127.0.0.1:6379,allowadmin=true,abortConnect=false”进行操作,如:
        /// <connectionStrings>
        ///      <add name = "RedisHosts" connectionString="127.0.0.1:6379,allowadmin=true,abortConnect=false"/>
        /// </connectionStrings>
        /// 
        /// 数据库编号
        public RedisHelper(int dbNum = 0) : this(null, dbNum)
        {
        }
        /// 
        /// 构造函数
        /// 
        /// Redis服务器连接字符串,格式:127.0.0.1:6379,allowadmin=true,abortConnect=false
        /// 数据库的编号
        public RedisHelper(string readWriteHosts, int dbNum = 0)
        {
            DbNum = dbNum;
            _conn = string.IsNullOrWhiteSpace(readWriteHosts) ? ConnectionMultiplexer.Connect(ConfigurationOptions.Parse(RedisConnectionString)) : ConnectionMultiplexer.Connect(ConfigurationOptions.Parse(readWriteHosts));
            //_conn.ConfigurationChanged += MuxerConfigurationChanged;
            _conn.ConfigurationChanged += ConfigurationChanged;
            //_conn.ConnectionFailed += MuxerConnectionFailed;
            _conn.ConnectionFailed += ConnectionFailed;
            //_conn.ConnectionRestored += MuxerConnectionRestored;
            _conn.ConnectionRestored += ConnectionRestored;
            //_conn.ErrorMessage += MuxerErrorMessage;
            _conn.ErrorMessage += ErrorMessage;
            //_conn.HashSlotMoved += MuxerHashSlotMoved;
            _conn.HashSlotMoved += HashSlotMoved;
            //_conn.InternalError += MuxerInternalError;
            _conn.InternalError += InternalError;
        }
        /// 
        /// 构造函数
        /// 
        /// Redis服务器连接字符串,格式:127.0.0.1:6379,allowadmin=true,abortConnect=false
        /// 数据库的编号
        /// 
        private RedisHelper(string readWriteHosts, int dbNum, int _)
        {
            DbNum = dbNum;
            readWriteHosts = string.IsNullOrWhiteSpace(readWriteHosts) ? RedisConnectionString : readWriteHosts;
            _conn = ConnectionCache.GetOrAdd(readWriteHosts, ConnectionMultiplexer.Connect(ConfigurationOptions.Parse(readWriteHosts)));
            //_conn.ConfigurationChanged += MuxerConfigurationChanged;
            _conn.ConfigurationChanged += ConfigurationChanged;
            //_conn.ConnectionFailed += MuxerConnectionFailed;
            _conn.ConnectionFailed += ConnectionFailed;
            //_conn.ConnectionRestored += MuxerConnectionRestored;
            _conn.ConnectionRestored += ConnectionRestored;
            //_conn.ErrorMessage += MuxerErrorMessage;
            _conn.ErrorMessage += ErrorMessage;
            //_conn.HashSlotMoved += MuxerHashSlotMoved;
            _conn.HashSlotMoved += HashSlotMoved;
            //_conn.InternalError += MuxerInternalError;
            _conn.InternalError += InternalError;
        }
        /// 
        /// 获取新实例
        /// 
        /// 数据库的编号
        /// 
        public static RedisHelper GetInstance(int db = 0)
        {
            return new RedisHelper(db);
        }
        /// 
        /// 获取单例
        /// 
        /// 数据库的编号
        /// 
        public static RedisHelper GetSingleInstance(int db = 0)
        {
            return new RedisHelper(null, db, 0);
        }
        /// 
        /// 从对象池获取默认实例
        /// 
        /// Redis服务器连接字符串,格式:127.0.0.1:6379,allowadmin=true,abortConnect=false
        /// 数据库的编号
        /// 
        public static RedisHelper GetInstance(string conn, int db = 0)
        {
            return new RedisHelper(conn, db);
        }
        /// 
        /// 获取单例
        /// 
        /// Redis服务器连接字符串,格式:127.0.0.1:6379,allowadmin=true,abortConnect=false
        /// 数据库的编号
        /// 
        public static RedisHelper GetSingleInstance(string conn, int db = 0)
        {
            return new RedisHelper(conn, db, 0);
        }
        #endregion 构造函数
        #region String
        #region 同步方法
        /// 
        /// 保存单个key value
        /// 
        /// Redis Key
        /// 保存的值
        /// 过期时间
        /// 是否保存成功
        public bool SetString(string key, string value, TimeSpan? expiry = default(TimeSpan?))
        {
            key = AddSysCustomKey(key);
            return Do(db => db.StringSet(key, value, expiry));
        }
        /// 
        /// 保存多个key value
        /// 
        /// 键值对
        /// 是否保存成功
        public bool SetString(List> keyValues)
        {
            List> newkeyValues = keyValues.Select(p => new KeyValuePair(AddSysCustomKey(p.Key), p.Value)).ToList();
            return Do(db => db.StringSet(newkeyValues.ToArray()));
        }
        /// 
        /// 保存一个对象
        /// 
        /// 对象类型
        /// 键
        /// 值
        /// 过期时间
        /// 是否保存成功
        public bool SetString(string key, T obj, TimeSpan? expiry = default(TimeSpan?))
        {
            key = AddSysCustomKey(key);
            string json = ConvertJson(obj);
            return Do(db => db.StringSet(key, json, expiry));
        }
        /// 
        /// 获取单个key的值
        /// 
        /// 键
        /// 值
        public string GetString(string key)
        {
            if (KeyExists(key))
            {
                key = AddSysCustomKey(key);
                return Do(db => db.StringGet(key));
            }
            return string.Empty;
        }
        /// 
        /// 获取多个Key
        /// 
        /// 键集合
        /// 值集合
        public RedisValue[] GetString(List listKey)
        {
            List newKeys = listKey.Select(AddSysCustomKey).ToList();
            return Do(db => db.StringGet(ConvertRedisKeys(newKeys)));
        }
        /// 
        /// 获取一个key的对象
        /// 
        /// 数据类型
        /// 键
        /// 实例对象
        public T GetString(string key)
        {
            if (KeyExists(key))
            {
                key = AddSysCustomKey(key);
                return Do(db => ConvertObj(db.StringGet(key)));
            }
            return default(T);
        }
        /// 
        /// 为数字增长val
        /// 
        /// 键
        /// 可以为负
        /// 增长后的值
        public double StringIncrement(string key, double val = 1)
        {
            key = AddSysCustomKey(key);
            return Do(db => db.StringIncrement(key, val));
        }
        /// 
        /// 为数字减少val
        /// 
        /// 键
        /// 可以为负
        /// 减少后的值
        public double StringDecrement(string key, double val = 1)
        {
            key = AddSysCustomKey(key);
            return Do(db => db.StringDecrement(key, val));
        }
        #endregion 同步方法
        #region 异步方法
        /// 
        /// 保存单个key value
        /// 
        /// Redis Key
        /// 保存的值
        /// 过期时间
        /// 是否保存成功
        public async Task SetStringAsync(string key, string value, TimeSpan? expiry = default(TimeSpan?))
        {
            key = AddSysCustomKey(key);
            return await Do(async db => await db.StringSetAsync(key, value, expiry));
        }
        /// 
        /// 保存多个key value
        /// 
        /// 键值对
        /// 是否保存成功
        public async Task SetStringAsync(List> keyValues)
        {
            List> newkeyValues = keyValues.Select(p => new KeyValuePair(AddSysCustomKey(p.Key), p.Value)).ToList();
            return await Do(async db => await db.StringSetAsync(newkeyValues.ToArray()));
        }
        /// 
        /// 保存一个对象
        /// 
        /// 数据类型
        /// 键
        /// 需要被缓存的对象
        /// 过期时间
        /// 是否保存成功
        public async Task SetStringAsync(string key, T obj, TimeSpan? expiry = default(TimeSpan?))
        {
            key = AddSysCustomKey(key);
            string json = ConvertJson(obj);
            return await Do(async db => await db.StringSetAsync(key, json, expiry));
        }
        /// 
        /// 获取单个key的值
        /// 
        /// 键
        /// 值
        public async Task GetStringAsync(string key)
        {
            if (KeyExists(key))
            {
                key = AddSysCustomKey(key);
                return await Do(async db => await db.StringGetAsync(key));
            }
            return string.Empty;
        }
        /// 
        /// 获取多个Key
        /// 
        /// 键集合
        /// 值集合
        public async Task GetStringAsync(List listKey)
        {
            List newKeys = listKey.Select(AddSysCustomKey).ToList();
            return await Do(async db => await db.StringGetAsync(ConvertRedisKeys(newKeys)));
        }
        /// 
        /// 获取一个key的对象
        /// 
        /// 数据类型
        /// 键
        /// 实例对象
        public async Task GetStringAsync(string key)
        {
            if (KeyExists(key))
            {
                key = AddSysCustomKey(key);
                string result = await Do(async db => await db.StringGetAsync(key));
                return ConvertObj(result);
            }
            return default(T);
        }
        /// 
        /// 为数字增长val
        /// 
        /// 键
        /// 可以为负
        /// 增长后的值
        public async Task IncrementStringAsync(string key, double val = 1)
        {
            key = AddSysCustomKey(key);
            return await Do(async db => await db.StringIncrementAsync(key, val));
        }
        /// 
        /// 为数字减少val
        /// 
        /// 键
        /// 可以为负
        /// 减少后的值
        public async Task DecrementStringAsync(string key, double val = 1)
        {
            key = AddSysCustomKey(key);
            return await Do(async db => await db.StringDecrementAsync(key, val));
        }
        #endregion 异步方法
        #endregion String
        #region Hash
        #region 同步方法
        /// 
        /// 判断某个数据是否已经被缓存
        /// 
        /// 键
        /// 对象的字段
        /// 是否缓存成功
        public bool HashExists(string key, string dataKey)
        {
            key = AddSysCustomKey(key);
            return Do(db => db.HashExists(key, dataKey));
        }
        /// 
        /// 存储数据到hash表
        /// 
        /// 数据类型
        /// 键
        /// 对象的字段
        /// 对象实例
        /// 是否存储成功
        public bool SetHash(string key, string dataKey, T t)
        {
            key = AddSysCustomKey(key);
            return Do(db =>
            {
                string json = ConvertJson(t);
                return db.HashSet(key, dataKey, json);
            });
        }
        /// 
        /// 存储数据到hash表
        /// 
        /// 数据类型
        /// 键
        /// 对象的字段
        /// 对象实例
        /// 过期时间
        /// 是否存储成功
        public bool SetHash(string key, string dataKey, T t, TimeSpan expire)
        {
            bool b = SetHash(key, dataKey, t);
            Expire(key, expire);
            return b;
        }
        /// 
        /// 移除hash中的某值
        /// 
        /// 键
        /// 对象的字段
        /// 是否移除成功
        public bool DeleteHash(string key, string dataKey)
        {
            key = AddSysCustomKey(key);
            return Do(db => db.HashDelete(key, dataKey));
        }
        /// 
        /// 移除hash中的多个值
        /// 
        /// 键
        /// 对象的字段集合
        /// 数量
        public long DeleteHash(string key, List dataKeys)
        {
            key = AddSysCustomKey(key);
            //List dataKeys1 = new List() {"1","2"};
            return Do(db => db.HashDelete(key, dataKeys.ToArray()));
        }
        /// 
        /// 从hash表获取数据
        /// 
        /// 数据类型
        /// 键
        /// 对象的字段
        /// 对象实例
        public T GetHash(string key, string dataKey)
        {
            if (KeyExists(key))
            {
                key = AddSysCustomKey(key);
                return Do(db =>
                {
                    string value = db.HashGet(key, dataKey);
                    return ConvertObj(value);
                });
            }
            return default(T);
        }
        /// 
        /// 为数字增长val
        /// 
        /// 键
        /// 对象的字段
        /// 可以为负
        /// 增长后的值
        public double IncrementHash(string key, string dataKey, double val = 1)
        {
            key = AddSysCustomKey(key);
            return Do(db => db.HashIncrement(key, dataKey, val));
        }
        /// 
        /// 为数字减少val
        /// 
        /// 键
        /// 对象的字段
        /// 可以为负
        /// 减少后的值
        public double DecrementHash(string key, string dataKey, double val = 1)
        {
            key = AddSysCustomKey(key);
            return Do(db => db.HashDecrement(key, dataKey, val));
        }
        /// 
        /// 获取hashkey所有Redis key
        /// 
        /// 数据类型
        /// 键
        /// 数据集合
        public List HashKeys(string key)
        {
            key = AddSysCustomKey(key);
            return Do(db =>
            {
                RedisValue[] values = db.HashKeys(key);
                return ConvetList(values);
            });
        }
        #endregion 同步方法
        #region 异步方法
        /// 
        /// 判断某个数据是否已经被缓存
        /// 
        /// 键
        /// 对象的字段
        /// 是否缓存成功
        public async Task ExistsHashAsync(string key, string dataKey)
        {
            key = AddSysCustomKey(key);
            return await Do(async db => await db.HashExistsAsync(key, dataKey));
        }
        /// 
        /// 存储数据到hash表
        /// 
        /// 数据类型
        /// 键
        /// 对象的字段
        /// 对象实例
        /// 是否存储成功
        public async Task SetHashAsync(string key, string dataKey, T t)
        {
            key = AddSysCustomKey(key);
            return await Do(async db =>
            {
                string json = ConvertJson(t);
                return await db.HashSetAsync(key, dataKey, json);
            });
        }
        /// 
        /// 存储数据到hash表
        /// 
        /// 数据类型
        /// 键
        /// 对象的字段
        /// 对象实例
        /// 过期时间
        /// 是否存储成功
        public async Task SetHashAsync(string key, string dataKey, T t, TimeSpan expire)
        {
            var b = await SetHashAsync(key, dataKey, t);
            Expire(key, expire);
            return b;
        }
        /// 
        /// 移除hash中的某值
        /// 
        /// 键
        /// 对象的字段
        /// 是否移除成功
        public async Task DeleteHashAsync(string key, string dataKey)
        {
            key = AddSysCustomKey(key);
            return await Do(async db => await db.HashDeleteAsync(key, dataKey));
        }
        /// 
        /// 移除hash中的多个值
        /// 
        /// 键
        /// 对象的字段集合
        /// 数量
        public async Task DeleteHashAsync(string key, List dataKeys)
        {
            key = AddSysCustomKey(key);
            return await Do(async db => await db.HashDeleteAsync(key, dataKeys.ToArray()));
        }
        /// 
        /// 从hash表获取数据
        /// 
        /// 数据类型
        /// 键
        /// 对象的字段
        /// 对象实例
        public async Task GetHashAsync(string key, string dataKey)
        {
            if (KeyExists(key))
            {
                key = AddSysCustomKey(key);
                string value = await Do(async db => await db.HashGetAsync(key, dataKey));
                return ConvertObj(value);
            }
            return default(T);
        }
        /// 
        /// 为数字增长val
        /// 
        /// 键
        /// 对象的字段
        /// 可以为负
        /// 增长后的值
        public async Task IncrementHashAsync(string key, string dataKey, double val = 1)
        {
            key = AddSysCustomKey(key);
            return await Do(async db => await db.HashIncrementAsync(key, dataKey, val));
        }
        /// 
        /// 为数字减少val
        /// 
        /// 键
        /// 对象的字段
        /// 可以为负
        /// 减少后的值
        public async Task DecrementHashAsync(string key, string dataKey, double val = 1)
        {
            key = AddSysCustomKey(key);
            return await Do(async db => await db.HashDecrementAsync(key, dataKey, val));
        }
        /// 
        /// 获取hashkey所有Redis key
        /// 
        /// 数据类型
        /// 键
        /// 数据集合
        public async Task> HashKeysAsync(string key)
        {
            key = AddSysCustomKey(key);
            RedisValue[] values = await Do(async db => await db.HashKeysAsync(key));
            return ConvetList(values);
        }
        #endregion 异步方法
        #endregion Hash
        #region List
        #region 同步方法
        /// 
        /// 移除指定ListId的内部List的值
        /// 
        /// 数据类型
        /// 键
        /// 值
        public void RemoveList(string key, T value)
        {
            key = AddSysCustomKey(key);
            Do(db => db.ListRemove(key, ConvertJson(value)));
        }
        /// 
        /// 获取指定key的List
        /// 
        /// 数据类型
        /// 键
        /// 数据集
        public List ListRange(string key)
        {
            if (KeyExists(key))
            {
                key = AddSysCustomKey(key);
                return Do(redis =>
                {
                    var values = redis.ListRange(key);
                    return ConvetList(values);
                });
            }
            return new List();
        }
        /// 
        /// 入队
        /// 
        /// 数据类型
        /// 键
        /// 值
        public void ListRightPush(string key, T value)
        {
            key = AddSysCustomKey(key);
            Do(db => db.ListRightPush(key, ConvertJson(value)));
        }
        /// 
        /// 出队
        /// 
        /// 数据类型
        /// 键
        /// 值
        public T ListRightPop(string key)
        {
            if (KeyExists(key))
            {
                key = AddSysCustomKey(key);
                return Do(db =>
                {
                    var value = db.ListRightPop(key);
                    return ConvertObj(value);
                });
            }
            return default(T);
        }
        /// 
        /// 入栈
        /// 
        /// 数据类型
        /// 键
        /// 值
        public void ListLeftPush(string key, T value)
        {
            key = AddSysCustomKey(key);
            Do(db => db.ListLeftPush(key, ConvertJson(value)));
        }
        /// 
        /// 出栈
        /// 
        /// 数据类型
        /// 键
        /// 对象实例
        public T ListLeftPop(string key)
        {
            if (KeyExists(key))
            {
                key = AddSysCustomKey(key);
                return Do(db =>
                {
                    var value = db.ListLeftPop(key);
                    return ConvertObj(value);
                });
            }
            return default(T);
        }
        /// 
        /// 获取集合中的数量
        /// 
        /// 键
        /// 数量
        public long ListLength(string key)
        {
            key = AddSysCustomKey(key);
            return Do(redis => redis.ListLength(key));
        }
        #endregion 同步方法
        #region 异步方法
        /// 
        /// 移除指定ListId的内部List的值
        /// 
        /// 键
        /// 值
        public async Task RemoveListAsync(string key, T value)
        {
            key = AddSysCustomKey(key);
            return await Do(async db => await db.ListRemoveAsync(key, ConvertJson(value)));
        }
        /// 
        /// 获取指定key的List
        /// 
        /// 数据类型
        /// 键
        /// 数据集合
        public async Task> ListRangeAsync(string key)
        {
            if (KeyExists(key))
            {
                key = AddSysCustomKey(key);
                var values = await Do(async redis => await redis.ListRangeAsync(key));
                return ConvetList(values);
            }
            return new List();
        }
        /// 
        /// 入队
        /// 
        /// 数据类型
        /// 键
        /// 值
        public async Task ListRightPushAsync(string key, T value)
        {
            key = AddSysCustomKey(key);
            return await Do(async db => await db.ListRightPushAsync(key, ConvertJson(value)));
        }
        /// 
        /// 出队
        /// 
        /// 数据类型
        /// 键
        /// 对象实例
        public async Task ListRightPopAsync(string key)
        {
            if (KeyExists(key))
            {
                key = AddSysCustomKey(key);
                var value = await Do(async db => await db.ListRightPopAsync(key));
                return ConvertObj(value);
            }
            return default(T);
        }
        /// 
        /// 入栈
        /// 
        /// 数据类型
        /// 键
        /// 值
        public async Task ListLeftPushAsync(string key, T value)
        {
            key = AddSysCustomKey(key);
            return await Do(async db => await db.ListLeftPushAsync(key, ConvertJson(value)));
        }
        /// 
        /// 出栈
        /// 
        /// 数据类型
        /// 键
        /// 实例对象
        public async Task ListLeftPopAsync(string key)
        {
            if (KeyExists(key))
            {
                key = AddSysCustomKey(key);
                var value = await Do(async db => await db.ListLeftPopAsync(key));
                return ConvertObj(value);
            }
            return default(T);
        }
        /// 
        /// 获取集合中的数量
        /// 
        /// 键
        /// 数量
        public async Task ListLengthAsync(string key)
        {
            key = AddSysCustomKey(key);
            return await Do(async redis => await redis.ListLengthAsync(key));
        }
        #endregion 异步方法
        #endregion List
        #region SortedSet 有序集合
        #region 同步方法
        /// 
        /// 添加
        /// 
        /// 键
        /// 值
        /// 排序号
        public bool AddSortedSet(string key, T value, double score)
        {
            key = AddSysCustomKey(key);
            return Do(redis => redis.SortedSetAdd(key, ConvertJson(value), score));
        }
        /// 
        /// 删除
        /// 
        /// 键
        /// 值
        public bool RemoveSortedSet(string key, T value)
        {
            key = AddSysCustomKey(key);
            return Do(redis => redis.SortedSetRemove(key, ConvertJson(value)));
        }
        /// 
        /// 获取全部
        /// 
        /// 键
        /// 数据集合
        public List SetRangeSortedByRank(string key)
        {
            if (KeyExists(key))
            {
                key = AddSysCustomKey(key);
                return Do(redis =>
                {
                    var values = redis.SortedSetRangeByRank(key);
                    return ConvetList(values);
                });
            }
            return new List();
        }
        /// 
        /// 获取集合中的数量
        /// 
        /// 键
        /// 数量
        public long SetSortedLength(string key)
        {
            key = AddSysCustomKey(key);
            return Do(redis => redis.SortedSetLength(key));
        }
        #endregion 同步方法
        #region 异步方法
        /// 
        /// 添加
        /// 
        /// 键
        /// 值
        /// 排序号
        public async Task SortedSetAddAsync(string key, T value, double score)
        {
            key = AddSysCustomKey(key);
            return await Do(async redis => await redis.SortedSetAddAsync(key, ConvertJson(value), score));
        }
        /// 
        /// 删除
        /// 
        /// 键
        /// 值
        public async Task SortedSetRemoveAsync(string key, T value)
        {
            key = AddSysCustomKey(key);
            return await Do(async redis => await redis.SortedSetRemoveAsync(key, ConvertJson(value)));
        }
        /// 
        /// 获取全部
        /// 
        /// 键
        /// 数据集合
        public async Task> SortedSetRangeByRankAsync(string key)
        {
            if (KeyExists(key))
            {
                key = AddSysCustomKey(key);
                var values = await Do(async redis => await redis.SortedSetRangeByRankAsync(key));
                return ConvetList(values);
            }
            return new List();
        }
        /// 
        /// 获取集合中的数量
        /// 
        /// 键
        /// 数量
        public async Task SortedSetLengthAsync(string key)
        {
            key = AddSysCustomKey(key);
            return await Do(async redis => await redis.SortedSetLengthAsync(key));
        }
        #endregion 异步方法
        #endregion SortedSet 有序集合
        #region key
        /// 
        /// 删除单个key
        /// 
        /// redis key
        /// 是否删除成功
        public bool DeleteKey(string key)
        {
            key = AddSysCustomKey(key);
            return Do(db => db.KeyDelete(key));
        }
        /// 
        /// 删除多个key
        /// 
        /// rediskey
        /// 成功删除的个数
        public long DeleteKey(List keys)
        {
            List newKeys = keys.Select(AddSysCustomKey).ToList();
            return Do(db => db.KeyDelete(ConvertRedisKeys(newKeys)));
        }
        /// 
        /// 判断key是否存储
        /// 
        /// 键
        /// 是否存储成功
        public bool KeyExists(string key)
        {
            key = AddSysCustomKey(key);
            return Do(db => db.KeyExists(key));
        }
        /// 
        /// 重新命名key
        /// 
        /// 旧的键
        /// 新的键
        /// 处理结果
        public bool RenameKey(string key, string newKey)
        {
            key = AddSysCustomKey(key);
            return Do(db => db.KeyRename(key, newKey));
        }
        /// 
        /// 设置Key的过期时间
        /// 
        /// 键
        /// 过期时间
        /// 处理结果
        public bool Expire(string key, TimeSpan? expiry = default(TimeSpan?))
        {
            key = AddSysCustomKey(key);
            return Do(db => db.KeyExpire(key, expiry));
        }
        #endregion key
        #region 发布订阅
        /// 
        /// Redis发布订阅  订阅
        /// 
        /// 订阅频道
        /// 处理过程
        public void Subscribe(string subChannel, Action handler = null)
        {
            ISubscriber sub = _conn.GetSubscriber();
            sub.Subscribe(subChannel, (channel, message) =>
            {
                if (handler == null)
                {
                    Console.WriteLine(subChannel + " 订阅收到消息:" + message);
                }
                else
                {
                    handler(channel, message);
                }
            });
        }
        /// 
        /// Redis发布订阅  发布
        /// 
        /// 消息对象
        /// 发布频道
        /// 消息
        /// 消息的数量
        public long Publish(string channel, T msg)
        {
            ISubscriber sub = _conn.GetSubscriber();
            return sub.Publish(channel, ConvertJson(msg));
        }
        /// 
        /// Redis发布订阅  取消订阅
        /// 
        /// 频道
        public void Unsubscribe(string channel)
        {
            ISubscriber sub = _conn.GetSubscriber();
            sub.Unsubscribe(channel);
        }
        /// 
        /// Redis发布订阅  取消全部订阅
        /// 
        public void UnsubscribeAll()
        {
            ISubscriber sub = _conn.GetSubscriber();
            sub.UnsubscribeAll();
        }
        #endregion 发布订阅
        #region 其他
        /// 
        /// 创建一个事务
        /// 
        /// 事务对象
        public ITransaction CreateTransaction()
        {
            return GetDatabase().CreateTransaction();
        }
        /// 
        /// 获得一个数据库实例
        /// 
        /// 数据库实例
        public IDatabase GetDatabase()
        {
            return _conn.GetDatabase(DbNum);
        }
        /// 
        /// 获得一个服务器实例
        /// 
        /// 服务器地址
        /// 服务器实例
        public IServer GetServer(string hostAndPort = null)
        {
            hostAndPort = string.IsNullOrEmpty(hostAndPort) ? _conn.Configuration.Split(',')[0] : hostAndPort;
            return _conn.GetServer(hostAndPort);
        }
        /// 
        /// 设置前缀
        /// 
        /// 前缀
        public void SetSysCustomKey(string customKey)
        {
            CustomKey = customKey;
        }
        #endregion 其他
        #region 辅助方法
        private string AddSysCustomKey(string oldKey)
        {
            var prefixKey = CustomKey ?? String.Empty;
            return prefixKey + oldKey;
        }
        private T Do(Func func)
        {
            var database = _conn.GetDatabase(DbNum);
            return func(database);
        }
        private string ConvertJson(T value)
        {
            return JsonConvert.SerializeObject(value);
        }
        private T ConvertObj(RedisValue value)
        {
            return JsonConvert.DeserializeObject(value);
        }
        private List ConvetList(RedisValue[] values)
        {
            List result = new List();
            foreach (var item in values)
            {
                var model = ConvertObj(item);
                result.Add(model);
            }
            return result;
        }
        private RedisKey[] ConvertRedisKeys(List redisKeys)
        {
            return redisKeys.Select(redisKey => (RedisKey)redisKey).ToArray();
        }
        #endregion 辅助方法
        #region 事件
        ///// 
        ///// 配置更改时
        ///// 
        ///// 触发者
        ///// 事件参数
        //private static void MuxerConfigurationChanged(object sender, EndPointEventArgs e)
        //{
        //    Console.WriteLine("Configuration changed: " + e.EndPoint);
        //}
        ///// 
        ///// 发生错误时
        ///// 
        ///// 
        ///// 
        //private static void MuxerErrorMessage(object sender, RedisErrorEventArgs e)
        //{
        //    Console.WriteLine("ErrorMessage: " + e.Message);
        //}
        ///// 
        ///// 重新建立连接之前的错误
        ///// 
        ///// 
        ///// 
        //private static void MuxerConnectionRestored(object sender, ConnectionFailedEventArgs e)
        //{
        //    Console.WriteLine("ConnectionRestored: " + e.EndPoint);
        //}
        ///// 
        ///// 连接失败 , 如果重新连接成功你将不会收到这个通知
        ///// 
        ///// 
        ///// 
        //private static void MuxerConnectionFailed(object sender, ConnectionFailedEventArgs e)
        //{
        //    Console.WriteLine("重新连接:Endpoint failed: " + e.EndPoint + ", " + e.FailureType + (e.Exception == null ? "" : (", " + e.Exception.Message)));
        //}
        ///// 
        ///// 更改集群
        ///// 
        ///// 
        ///// 
        //private static void MuxerHashSlotMoved(object sender, HashSlotMovedEventArgs e)
        //{
        //    Console.WriteLine("HashSlotMoved:NewEndPoint" + e.NewEndPoint + ", OldEndPoint" + e.OldEndPoint);
        //}
        ///// 
        ///// redis类库错误
        ///// 
        ///// 
        ///// 
        //private static void MuxerInternalError(object sender, InternalErrorEventArgs e)
        //{
        //    Console.WriteLine("InternalError:Message" + e.Exception.Message);
        //}
        #endregion 事件
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        public void Dispose()
        {
            _conn.Dispose();
        }
    }
}