C# 项目中使用 ServiceStack.Redis 操作 Redis

Redis 官网上可以找到很多针对 C# 的类库支持,这里我们选择了 ServiceStack.Redis 这个客户端,但是 ServiceStack.Redis 有个连接数限制,需要修改源码,另外一个用的比较多的是 StackExchange.Redis,这里不做介绍。

RedisConfiguration 类:

    /// <summary>
    /// 表示配置文件中的 Redis 配置节。
    /// </summary>
    public sealed class RedisConfiguration : ConfigurationSection
    {
        /// <summary>
        /// 检索当前应用程序默认配置的 Redis 配置节。
        /// </summary>
        /// <returns>指定的 Redis 配置节对象,或者,如果该节不存在,则为 null。</returns>
        public static RedisConfiguration GetConfig()
        {
            RedisConfiguration section = (RedisConfiguration)ConfigurationManager.GetSection("RedisConfig");
            return section;
        }

        /// <summary>
        /// 检索当前应用程序默认配置的 Redis 配置节。
        /// </summary>
        /// <param name="sectionName">配置节的路径和名称。</param>
        /// <returns>指定的 Redis 配置节对象,或者,如果该节不存在,则为 null。</returns>
        public static RedisConfiguration GetConfig(string sectionName)
        {
            RedisConfiguration section = (RedisConfiguration)ConfigurationManager.GetSection("RedisConfig");
            if (section == null)
                throw new ConfigurationErrorsException("Section " + sectionName + " is not found.");
            return section;
        }
        /// <summary>
        /// 获取或设置用于写入的 Redis 服务器地址。
        /// </summary>
        [ConfigurationProperty("WriteServerList", IsRequired = false)]
        public string WriteServerHosts
        {
            get
            {
                return (string)base["WriteServerList"];
            }
            set
            {
                base["WriteServerList"] = value;
            }
        }

        /// <summary>
        /// 获取或设置用于读取的 Redis 服务器的主机地址。
        /// </summary>
        [ConfigurationProperty("ReadServerList", IsRequired = false)]
        public string ReadServerHosts
        {
            get
            {
                return (string)base["ReadServerList"];
            }
            set
            {
                base["ReadServerList"] = value;
            }
        }

        /// <summary>
        /// 获取或设置 Redis Sentinel 服务器的主机地址。
        /// </summary>
        [ConfigurationProperty("SentinelServerList", IsRequired = false)]
        public string SentinelServerHosts
        {
            get
            {
                return (string)base["SentinelServerList"];
            }
            set
            {
                base["SentinelServerList"] = value;
            }
        }

        /// <summary>
        /// 获取或设置 Redis Sentinel 服务器的密码。
        /// </summary>
        [ConfigurationProperty("SentinelPassword", IsRequired = false)]
        public string SentinelPassword
        {
            get
            {
                return (string)base["SentinelPassword"];
            }
            set
            {
                base["SentinelPassword"] = value;
            }
        }

        /// <summary>
        /// 获取或设置 Redis 主服务器的名称。
        /// </summary>
        [ConfigurationProperty("MasterName", IsRequired = false)]
        public string MasterName
        {
            get
            {
                string masterName = (string)base["MasterName"];
                return String.IsNullOrEmpty(masterName) ? "master" : masterName;
            }
            set
            {
                base["MasterName"] = value;
            }
        }

        /// <summary>
        /// 获取或设置 Sentinel 的默认数据库。
        /// </summary>
        [ConfigurationProperty("SentinelDb", IsRequired = false, DefaultValue = 0)]
        public int SentinelDb
        {
            get
            {
                int sentinelDb = (int)base["SentinelDb"];
                return sentinelDb >= 0 ? sentinelDb : 0;
            }
            set
            {
                base["SentinelDb"] = value;
            }
        }

        /// <summary>
        /// 最大写入连接池大小。
        /// </summary>
        [ConfigurationProperty("MaxWritePoolSize", IsRequired = false, DefaultValue = 5)]
        public int MaxWritePoolSize
        {
            get
            {
                int maxWritePoolSize = (int)base["MaxWritePoolSize"];
                return maxWritePoolSize > 0 ? maxWritePoolSize : 5;
            }
            set
            {
                base["MaxWritePoolSize"] = value;
            }
        }

        /// <summary>
        /// 最大读取连接池大小。
        /// </summary>
        [ConfigurationProperty("MaxReadPoolSize", IsRequired = false, DefaultValue = 5)]
        public int MaxReadPoolSize
        {
            get
            {
                int maxReadPoolSize = (int)base["MaxReadPoolSize"];
                return maxReadPoolSize > 0 ? maxReadPoolSize : 5;
            }
            set
            {
                base["MaxReadPoolSize"] = value;
            }
        }

        /// <summary>
        /// 自动重启。
        /// </summary>
        [ConfigurationProperty("AutoStart", IsRequired = false, DefaultValue = true)]
        public bool AutoStart
        {
            get
            {
                return (bool)base["AutoStart"];
            }
            set
            {
                base["AutoStart"] = value;
            }
        }

        /// <summary>
        /// 本地缓存到期时间,单位:秒。
        /// </summary>
        [ConfigurationProperty("CacheExpires", IsRequired = false, DefaultValue = 36000)]
        public int CacheExpires
        {
            get
            {
                return (int)base["CacheExpires"];
            }
            set
            {
                base["CacheExpires"] = value;
            }
        }


        /// <summary>
        /// 是否记录日志,该设置仅用于排查 Redis 运行时出现的问题,如 Redis 工作正常,请关闭该项。
        /// </summary>
        [ConfigurationProperty("RecordeLog", IsRequired = false, DefaultValue = false)]
        public bool RecordeLog
        {
            get
            {
                return (bool)base["RecordeLog"];
            }
            set
            {
                base["RecordeLog"] = value;
            }
        }

    }

RedisKeys 类定义全局 Key:

    /// <summary>
    /// 全局 Key 定义。
    /// </summary>
    public static class RedisKeys
    {

        #region 广告相关...

        /// <summary>
        /// 指定城市唯一编号指定唯一广告编号的信息实体对象,{0}:指定城市唯一编号,{1}:指定广告编码。
        /// </summary>
        public static readonly string ADVERTISEMENTSEAT_CITY_BAIDUADID = "AdvertisementSeat_City_{0}_BaiDuAdId_{1}";
        /// <summary>
        /// 指定城市唯一编号指定广告投放目标的信息实体对象,{0}:指定城市唯一编号,{1}:指定广告投放目标。
        /// </summary>
        public static readonly string ADVERTISEMENTSEAT_CITY_BAIDUADID_TARGET = "AdvertisementSeat_City_{0}_Target_{1}";
        /// <summary>
        /// 指定城市唯一编号指定唯一广告编号的信息实体对象,{0}:指定城市唯一编号,{1}:指定产品类型编码。
        /// </summary>
        public static readonly string ADVERTISEMENTSEAT_CITY_CONDITION = "AdvertisementSeat_City_{0}_Condition_{1}";

        #endregion

    }

RedisConnectType 类定义 Redis 建立连接的方式,连接池模式,及时连接及时释放模式:

    /// <summary>
    /// 定义 Redis 建立连接的方式,连接池模式,及时连接及时释放模式。
    /// </summary>
    public enum RedisConnectType
    {
        /// <summary>
        /// 连接池链接方式。
        /// </summary>
        PooledRedisClient,
        /// <summary>
        /// 短连接方式,用完就释放的模式。
        /// </summary>
        ShortConnectClient
    }

RedisExpires 中统一定义了 Redis 数据的有效时间:

    /// <summary>
    /// Redis 有效时间(单位:分钟)定义类。
    /// </summary>
    public static class RedisExpires
    {
        /// <summary>
        /// 1 分钟。
        /// </summary>
        public static readonly int ONE_MINUTE = 1;

        /// <summary>
        /// 10 分钟。
        /// </summary>
        public static readonly int TEN_MINUTE = 10;

        /// <summary>
        /// 半小时。
        /// </summary>
        public static readonly int HALF_HOUR = 30;

        /// <summary>
        /// 1 小时。
        /// </summary>
        public static readonly int ONE_HOUR = 60;

        /// <summary>
        /// 半天。
        /// </summary>
        public static readonly int HALF_DAY = 60 * 12;

        /// <summary>
        /// 1 天。
        /// </summary>
        public static readonly int ONE_DAY = 60 * 24;

        /// <summary>
        /// 1 周。
        /// </summary>
        public static readonly int ONE_WEEK = 7 * 60 * 24;

        /// <summary>
        /// 1 个月。
        /// </summary>
        public static readonly int ONE_MONTH = 30 * 60 * 24;
    }

RedisManager 类中提供了常用的操作:

   /// <summary>
    /// 提供一组用于 Redis 连接池管理对象的工具和方法。
    /// </summary>
    public sealed class RedisManager
    {
        /// <summary>
        /// 声明 Redis 配置信息。
        /// </summary>
        private static RedisConfiguration _redisConfiguration = RedisConfiguration.GetConfig();
        /// <summary>
        /// 声明 Redis 客户端连接的线程安全池对象。
        /// </summary>
        private static IRedisClientsManager _redisClientsManager = null;
        ///// <summary>
        ///// 建立 Redis 连接的方式(默认是连接池的方式)。
        ///// </summary>
        //private RedisConnectType ConnnectType = RedisConnectType.PooledRedisClient;
        ///// <summary>
        ///// ip
        ///// </summary>
        //private string RedisServerIP = "";
        ///// <summary>
        ///// 端口
        ///// </summary>
        //private int RedisServerPort = 6379;
        ///// <summary>
        ///// 数据库编号
        ///// </summary>
        //private int RedisServerDb = 0;
        /// <summary>
        /// 声明 _lockObject 对象。
        /// </summary>
        private object _lockObject = new object();

        /// <summary>
        /// 初始化 Redis 连接池管理对象。
        /// </summary>
        static RedisManager()
        {
            CreateManager();
        }


        /// <summary>
        /// 创建 Redis 连接池管理对象。
        /// </summary>
        private static void CreateManager()
        {
            string[] sentinelServerHosts = SplitServerHosts(_RedisConfiguration.SentinelServerHosts, ",");
            var redisSentinel = new RedisSentinel(sentinelServerHosts, _RedisConfiguration.MasterName);
            _redisClientsManager = redisSentinel.Start();
        }

        /// <summary>
        /// 取得服务器主机地址集合。
        /// </summary>
        /// <param name="serverHosts">服务器主机地址。</param>
        /// <param name="split">分隔符。</param>
        /// <returns>服务器主机地址集合。</returns>
        private static string[] SplitServerHosts(string serverHosts, string split)
        {
            return serverHosts.Split(split.ToArray());
        }

        /// <summary>
        /// 获取 Redis 客户端缓存操作对象。
        /// </summary>
        public static IRedisClient GetClient()
        {
            if (_redisClientsManager == null)
                CreateManager();
            var redisClient = _redisClientsManager.GetClient();
            redisClient.Password = _RedisConfiguration.SentinelPassword;
#if(DEBUG)
            redisClient.Db = _RedisConfiguration.SentinelDb;
#endif
            return redisClient;
        }

        /// <summary>
        /// 刷新全部数据。
        /// </summary>
        public static void FlushAll()
        {
            using (IRedisClient redis = GetClient())
            {
                redis.FlushAll();
            }
        }

        #region 项...

        /// <summary>
        /// 设置指定的项到指定的键中。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <param name="t">指定的项。</param>
        /// <returns>如果设置成功,则为 true;否则为 false。</returns>
        public static bool ItemSet<T>(string key, T t)
        {
            using (IRedisClient redis = GetClient())
            {
                return redis.Set(key, t);
            }
        }

        /// <summary>
        /// 设置指定的项到指定的键中。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <param name="t">指定的项。</param>
        /// <param name="expire">指定的有效期(单位:分钟)。</param>
        /// <returns>如果设置成功,则为 true;否则为 false。</returns>
        public static bool ItemSetExpire<T>(string key, T t, int expire)
        {
            using (IRedisClient redis = GetClient())
            {
                return redis.Set(key, t, DateTime.Now.Add(TimeSpan.FromMinutes(expire)));
            }
        }

        /// <summary>
        /// 获取指定的键的项。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <returns>如果存在该项,则返回该项,否则返回 null。</returns>
        public static T ItemGet<T>(string key) where T : class
        {
            using (IRedisClient redis = GetClient())
            {
                return redis.Get<T>(key);
            }
        }

        /// <summary>
        /// 移除指定的键的项。
        /// </summary>
        /// <param name="key">指定的键。</param>
        /// <returns>如果移除成功,则为 true;否则为 false。</returns>
        public static bool ItemRemove(string key)
        {
            using (IRedisClient redis = GetClient())
            {
                return redis.Remove(key);
            }
        }

        #endregion

        #region 列表...

        /// <summary>
        /// 添加项到指定键的列表。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <param name="t">指定的项。</param>
        public static void ListAdd<T>(string key, T t)
        {
            using (IRedisClient redis = GetClient())
            {
                var redisTypedClient = redis.As<T>();
                redisTypedClient.AddItemToList(redisTypedClient.Lists[key], t);
            }
        }

        /// <summary>
        /// 将指定的对象集合的元素添加到指定键的列表末尾。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <param name="tList">指定的项的集合。</param>
        public static void ListAddRange<T>(string key, List<T> tList)
        {
            using (IRedisClient redis = GetClient())
            {
                var redisTypedClient = redis.As<T>();
                redisTypedClient.Lists[key].AddRange(tList);
            }
        }

        /// <summary>
        /// 从指定键的列表中移除指定的项。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <param name="t">指定的项。</param>
        /// <returns>返回一个值,该值表示是否移除成功。</returns>
        public static bool ListRemove<T>(string key, T t)
        {
            using (IRedisClient redis = GetClient())
            {
                var redisTypedClient = redis.As<T>();
                return redisTypedClient.RemoveItemFromList(redisTypedClient.Lists[key], t) > 0;
            }
        }

        /// <summary>
        /// 从指定键的列表中移除所有的项。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        public static void ListRemoveAll<T>(string key)
        {
            using (IRedisClient redis = GetClient())
            {
                var redisTypedClient = redis.As<T>();
                redisTypedClient.Lists[key].RemoveAll();
            }
        }

        /// <summary>
        /// 获取指定键的列表中实际包含的元素数。
        /// </summary>
        /// <param name="key">指定的键。</param>
        /// <returns>指定的键中实际包含的元素数。</returns>
        public static int ListCount(string key)
        {
            using (IRedisClient redis = GetClient())
            {
                return (int)redis.GetListCount(key);
            }
        }

        /// <summary>
        /// 从指定键的列表中获取指定范围的元素。
        /// </summary>
        /// <typeparam name="T">指定项的类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <param name="start">范围开始处的从零开始的索引。</param>
        /// <param name="count">范围中的元素数。</param>
        /// <returns>指定键的列表中的范围的元素。</returns>
        public static List<T> ListGetRange<T>(string key, int index, int count)
        {
            using (IRedisClient redis = GetClient())
            {
                var c = redis.As<T>();
                return c.Lists[key].GetRange(index, index + count - 1);
            }
        }

        /// <summary>
        /// 获取指定键的列表中的所有元素。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <returns>指定键的列表中的范围的元素。</returns>
        public static List<T> ListGetAll<T>(string key)
        {
            using (IRedisClient redis = GetClient())
            {
                var c = redis.As<T>();
                return c.Lists[key].GetRange(0, c.Lists[key].Count);
            }
        }

        /// <summary>
        /// 分页获取指定键的列表中的元素。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <param name="pageIndex">指定的分页索引。</param>
        /// <param name="pageSize">指定的分页大小。</param>
        /// <returns>指定键的列表中的范围的元素。</returns>
        public static List<T> ListGetAll<T>(string key, int pageIndex, int pageSize)
        {
            int start = pageSize * (pageIndex - 1);
            return ListGetRange<T>(key, start, pageSize);
        }

        /// <summary>
        /// 设置指定键的列表的有效期。
        /// </summary>
        /// <param name="key">指定的键。</param>
        /// <param name="datetime">有效期。</param>
        public static void ListSetExpire(string key, DateTime datetime)
        {
            using (IRedisClient redis = GetClient())
            {
                redis.ExpireEntryAt(key, datetime);
            }
        }

        #endregion

        #region 集合...

        /// <summary>
        /// 将一个或多个元素加入到集合指定的键中,已经存在于集合的元素将被忽略。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <param name="t">指定的项。</param>
        public static void SetAdd<T>(string key, T t)
        {
            using (IRedisClient redis = GetClient())
            {
                var redisTypedClient = redis.As<T>();
                redisTypedClient.Sets[key].Add(t);
            }
        }

        /// <summary>
        /// 获取指定的键的集合中实际包含的元素数。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <returns>指定的键的集合中实际包含的元素数。</returns>
        public static int SetCount<T>(string key)
        {
            using (IRedisClient redis = GetClient())
            {
                var redisTypedClient = redis.As<T>();
                return redisTypedClient.Sets[key].Count();
            }
        }

        /// <summary>
        /// 确定某项是否在指定键的集合中。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <param name="t">指定的项。</param>
        /// <returns>如果存在该项,则为 true;否则为 false。</returns>
        public static bool SetContains<T>(string key, T t)
        {
            using (IRedisClient redis = GetClient())
            {
                var redisTypedClient = redis.As<T>();
                return redisTypedClient.Sets[key].Contains(t);
            }
        }

        /// <summary>
        /// 从指定键的集合中移除特定对象的第一个匹配项。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <param name="t">指定的项。</param>
        /// <returns>如果移除成功,则为 true;否则为 false。</returns>
        public static bool SetRemove<T>(string key, T t)
        {
            using (IRedisClient redis = GetClient())
            {
                var redisTypedClient = redis.As<T>();
                return redisTypedClient.Sets[key].Remove(t);
            }
        }

        /// <summary>
        /// 获取指定键的数据集的所有项。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <returns>指定键的数据集的所有项</returns>
        public static IList<T> SetGetAll<T>(string key)
        {
            List<T> result = new List<T>();
            using (IRedisClient redis = GetClient())
            {
                var redisTypedClient = redis.As<T>();
                var sets = redisTypedClient.Sets[key];

                if (sets != null && sets.Count > 0)
                {
                    foreach (var item in sets)
                    {
                        result.Add(item);
                    }
                }
            }
            return result;
        }

        #endregion

        #region 哈希表...

        /// <summary>
        /// 确定某项是否在指定键的哈希表中。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <param name="dataKey">数据项的键。</param>
        /// <returns>如果存在该项,则为 true;否则为 false。</returns>
        public static bool HashSetContains<T>(string key, string dataKey)
        {
            using (IRedisClient redis = GetClient())
            {
                return redis.HashContainsEntry(key, dataKey);
            }
        }

        /// <summary>
        /// 设置指定的项到指定键的哈希表中。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <param name="dataKey">数据项的键。</param>
        /// <returns>如果设置成功,则为 true;否则为 false。</returns>
        public static bool HashSetAdd<T>(string key, string dataKey, T t)
        {
            using (IRedisClient redis = GetClient())
            {
                string value = JsonSerializer.SerializeToString(t);
                return redis.SetEntryInHash(key, dataKey, value);
            }
        }

        /// <summary>
        /// 移除哈希表中指定键的项。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <param name="dataKey">数据项的键。</param>
        /// <returns>如果移除成功,则为 true;否则为 false。</returns>
        public static bool HashSetRemove(string key, string dataKey)
        {
            using (IRedisClient redis = GetClient())
            {
                return redis.RemoveEntryFromHash(key, dataKey);
            }
        }

        /// <summary>
        /// 移除哈希表中的所有项。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <param name="dataKey">数据项的键。</param>
        /// <returns>如果移除成功,则为 true;否则为 false。</returns>
        public static bool HashSetRemoveAll(string key)
        {
            using (IRedisClient redis = GetClient())
            {
                return redis.Remove(key);
            }
        }

        /// <summary>
        /// 获取哈希表中的指定键的项。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <param name="dataKey">数据项的键。</param>
        /// <returns>指定键的哈希表的项。</returns>
        public static T HashSetGet<T>(string key, string dataKey)
        {
            using (IRedisClient redis = GetClient())
            {
                string value = redis.GetValueFromHash(key, dataKey);
                return JsonSerializer.DeserializeFromString<T>(value);
            }
        }

        /// <summary>
        /// 获取指定键的哈希表的所有项。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <returns>指定键的哈希表的所有项。</returns>
        public static List<T> HashSetGetAll<T>(string key)
        {
            using (IRedisClient redis = GetClient())
            {
                var list = redis.GetHashValues(key);
                if (list != null && list.Count > 0)
                {
                    List<T> result = new List<T>();
                    foreach (var item in list)
                    {
                        var value = JsonSerializer.DeserializeFromString<T>(item);
                        result.Add(value);
                    }
                    return result;
                }
                return null;
            }
        }

        /// <summary>
        /// 设置指定键的哈希表的有效期。
        /// </summary>
        /// <param name="key">指定的键。</param>
        /// <param name="expire">指定的有效期时间(单位:分钟)。</param>
        public static void HashSetExpire(string key, int expire)
        {
            using (IRedisClient redis = GetClient())
            {
                redis.ExpireEntryAt(key, DateTime.Now.Add(TimeSpan.FromMinutes(expire)));
            }
        }

        #endregion

        #region 有序集合...

        /// <summary>
        /// 添加指定项到指定键的有序集合。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <param name="t">指定的项。</param>
        /// <returns>如果成功添加,则为 true;否则为 false。</returns>
        public static bool SortedSetAdd<T>(string key, T t)
        {
            using (IRedisClient redis = GetClient())
            {
                string value = JsonSerializer.SerializeToString<T>(t);
                return redis.AddItemToSortedSet(key, value);
            }
        }


        /// <summary>
        /// 添加指定项到指定键的有序集合,评分用于排序。如果该元素已经存在,则根据评分更新该元素的顺序。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <param name="t">指定的项。</param>
        /// <param name="score">用于排序的评分值。</param>
        /// <returns>如果成功添加,则为 true;否则为 false。</returns>
        public static bool SortedSetAdd<T>(string key, T t, double score)
        {
            using (IRedisClient redis = GetClient())
            {
                string value = JsonSerializer.SerializeToString<T>(t);
                return redis.AddItemToSortedSet(key, value, score);
            }
        }

        /// <summary>
        /// 从指定键的有序集合中移除指定的元素。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <param name="t">指定的项。</param>
        /// <returns>如果成功移除,则为 true;否则为 false。</returns>
        public static bool SortedSetRemove<T>(string key, T t)
        {
            using (IRedisClient redis = GetClient())
            {
                string value = ServiceStack.Text.JsonSerializer.SerializeToString<T>(t);
                return redis.RemoveItemFromSortedSet(key, value);
            }
        }

        /// <summary>
        /// 从指定键的有序集合尾部移除指定的索引后的匹配项。
        /// </summary>
        /// <param name="key">指定的键。</param>
        /// <param name="size">保留的条数。</param>
        /// <returns>移除的元素数量。</returns>
        public static int SortedSetTrim(string key, int size)
        {
            using (IRedisClient redis = GetClient())
            {
                return (int)redis.RemoveRangeFromSortedSet(key, size, 9999999);
            }
        }

        /// <summary>
        /// 获取指定的键的有序集合中实际包含的元素数。
        /// </summary>
        /// <param name="key">指定的键。</param>
        /// <returns>指定的键的有序集合中实际包含的元素数。</returns>
        public static int SortedSetCount(string key)
        {
            using (IRedisClient redis = GetClient())
            {
                return (int)redis.GetSortedSetCount(key);
            }
        }

        /// <summary>
        /// 分页获取指定键的有序集合中的元素。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <param name="pageIndex">指定的分页索引。</param>
        /// <param name="pageSize">指定的分页大小。</param>
        /// <returns>指定键的有序集合中的元素集合。</returns>
        public static List<T> SortedSetGetList<T>(string key, int pageIndex, int pageSize)
        {
            using (IRedisClient redis = GetClient())
            {
                var list = redis.GetRangeFromSortedSet(key, (pageIndex - 1) * pageSize, pageIndex * pageSize - 1);
                if (list != null && list.Count > 0)
                {
                    List<T> result = new List<T>();
                    foreach (var item in list)
                    {
                        var data = ServiceStack.Text.JsonSerializer.DeserializeFromString<T>(item);
                        result.Add(data);
                    }
                    return result;
                }
            }
            return null;
        }


        /// <summary>
        /// 获取指定键的有序集合中的所有元素。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <returns>指定键的有序集合中的元素集合。</returns>
        public static List<T> SortedSetGetListALL<T>(string key)
        {
            using (IRedisClient redis = GetClient())
            {
                var list = redis.GetRangeFromSortedSet(key, 0, 9999999);
                if (list != null && list.Count > 0)
                {
                    List<T> result = new List<T>();
                    foreach (var item in list)
                    {
                        var data = JsonSerializer.DeserializeFromString<T>(item);
                        result.Add(data);
                    }
                    return result;
                }
            }
            return null;
        }

        /// <summary>
        /// 设置指定键的有序集合的有效期。
        /// </summary>
        /// <param name="key">指定的键。</param>
        /// <param name="expire">指定的有效期(单位:分钟)。</param>
        public static void SortedSetSetExpire(string key, int expire)
        {
            using (IRedisClient redis = GetClient())
            {
                redis.ExpireEntryAt(key, DateTime.Now.Add(TimeSpan.FromMinutes(expire)));
            }
        }

        /// <summary>
        /// 获取指定键的有序集合中的指定元素的评分。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <param name="t">指定的项。</param>
        /// <returns>指定键的有序集合中的指定元素的评分。</returns>
        public static double SortedSetGetItemScore<T>(string key, T t)
        {
            using (IRedisClient redis = GetClient())
            {
                var data = ServiceStack.Text.JsonSerializer.SerializeToString<T>(t);
                return redis.GetItemScoreInSortedSet(key, data);
            }
        }

        #endregion

        #region 二进制...

        /// <summary>
        /// 设置 BitMap 值,返回 0 或 1 是成功,返回 -1 是失败。
        /// </summary>
        /// <param name="key">指定的键。</param>
        /// <param name="offset">偏移量。</param>
        /// <param name="value">值只能是 0 或 1,其它的值会报错</param>
        /// <returns>返回 0 或 1 是成功,返回 -1 是失败。</returns>
        public static long BitSet(string key, int offset, int value)
        {
            using (IRedisClient redis = GetClient())
            {
                var rc = redis as RedisClient;
                if (rc != null)
                {
                    return rc.SetBit(key, offset, value);
                }
                return -1;
            }
        }

        /// <summary>
        /// 获取 BitMap 值,返回 0 或 1 是成功,返回 -1 是失败。
        /// </summary>
        /// <param name="key">指定的键。</param>
        /// <param name="offset">偏移量。</param>
        /// <returns>返回 0 或 1 是成功,返回 -1 是失败。</returns>
        public static long BitGet(string key, int offset)
        {
            using (IRedisClient redis = GetClient())
            {
                var rc = redis as RedisClient;
                if (rc != null)
                {
                    return rc.GetBit(key, offset);
                }
                return -1;
            }
        }

        public bool ByteSet<T>(string key, T t)
        {
            bool result = false;
            if (t != null)
            {
                MemoryStream ms = new MemoryStream();
                Serialize(t, ms);
                byte[] data = ms.ToArray();
                using (IRedisClient redis = GetClient())
                {
                    return redis.Set(key, data);
                }
            }
            return result;

        }

        /// <summary>
        /// 写入一个实体类T,将其转换成二制进存储,并且数据过期时间一到则立刻删除
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <param name="t"></param>
        /// <param name="Expire"></param>
        /// <returns></returns>
        public bool ByteSetExpire<T>(string key, T t, DateTime Expire)
        {
            bool flag = false;
            if (t != null)
            {
                MemoryStream ms = new MemoryStream();
                Serialize<T>(t, ms);
                byte[] data = ms.ToArray();
                using (IRedisClient redis = GetClient())
                {
                    TimeSpan ts = Expire - DateTime.Now;
                    flag = redis.Set(key, data, ts);
                }
            }
            return flag;
        }

        /// <summary>
        /// 获取 key 值为 key 的实体类 T。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="key">指定的键。</param>
        /// <returns></returns>
        public T ByteGet<T>(string key)
        {
            using (IRedisClient redis = GetClient())
            {
                byte[] data = redis.Get<byte[]>(key);
                if (data == null || data.Length == 0)
                {
                    return default(T);
                }
                using (MemoryStream ms = new MemoryStream())
                {
                    ms.Write(data, 0, data.Length);
                    ms.Position = 0;
                    return Deserialize<T>(ms);
                }
            }
        }

        #endregion

        #region 其他方法...

        /// <summary>
        /// 获取当前服务器中的所有 Key。
        /// </summary>
        /// <returns>当前服务器中的所有 Key 的集合。</returns>
        public static List<string> GetAllKeys()
        {
            using (IRedisClient redis = GetClient())
            {
                return redis.GetAllKeys();
            }
        }

        /// <summary>
        /// 移除指定集合中的所有 Key。
        /// </summary>
        /// <param name="keys">指定的 Key 集合。</param>
        public static void RemoveAll(IEnumerable<string> keys)
        {
            using (IRedisClient redis = GetClient())
            {
                redis.RemoveAll(keys);
            }
        }

        /// <summary>
        /// 确定指定的键是否在 Redis 数据库中。
        /// </summary>
        /// <param name="key">指定的键。</param>
        /// <returns>若存在指定的键,则返回 true,否则返回 false。</returns>
        public static bool ContainsKey(string key)
        {
            using (IRedisClient redis = GetClient())
            {
                return redis.ContainsKey(key);
            }
        }

        /// <summary>
        /// 获取当前数据库服务器中的指定的 Key。
        /// </summary>
        /// <param name="key">指定的键。</param>
        /// <returns>若移除指定的键成功,则返回 true,否则返回 false。</returns>
        public static bool Remove(string key)
        {
            using (IRedisClient redis = GetClient())
            {
                return redis.Remove(key);
            }
        }

        /// <summary>
        /// 获取当前 Redis 信息。
        /// </summary>
        /// <returns>当前 Redis 信息。</returns>
        public Dictionary<string, string> GetInfo()
        {
            using (IRedisClient redis = GetClient())
            {
                return redis.Info;
            }
        }

        /// <summary>
        /// 将指定的对象序列化成二进制对象。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="obj">指定的对象。</param>
        /// <param name="stream">序列化的二进制对象。</param>
        private static void Serialize<T>(T obj, Stream stream)
        {
            if (stream == null)
                throw new ArgumentNullException("stream");
            var formatter = new BinaryFormatter();
            formatter.Serialize(stream, obj);
        }

        /// <summary>
        /// 将指定的二进制对象反序列化成对象。
        /// </summary>
        /// <typeparam name="T">指定的项类型。</typeparam>
        /// <param name="obj">指定的对象。</param>
        /// <param name="stream">序列化的二进制对象。</param>
        /// <returns>反序列化的对象。</returns>
        public static T Deserialize<T>(Stream stream)
        {
            if (stream == null)
                throw new ArgumentNullException("stream");

            var formatter = new BinaryFormatter();
            return (T)formatter.Deserialize(stream);
        }

        #endregion

    }

  

 

 

 

posted @ 2012-04-06 16:09  Charles Zhang  阅读(2014)  评论(0编辑  收藏  举报