C# Redis库StackExchange.Redis,使用SortSet

1、StackExchange的安装可以参考:

https://www.cnblogs.com/cang12138/p/8884362.html

https://www.cnblogs.com/liqingwen/p/6672452.html

https://www.cnblogs.com/wangyulong/p/8656215.html

2、我自己参考写的封装

(1)redis.cs

using Newtonsoft.Json;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;

namespace YChain.SinDouGame.Services
{
    public class Redis : ICache
    {
        int Default_Timeout = 7 * 24 * 60 * 60;//默认超时时间(单位秒)
        string address;
        JsonSerializerSettings jsonConfig = new JsonSerializerSettings() { ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore, NullValueHandling = NullValueHandling.Ignore };
        ConnectionMultiplexer connectionMultiplexer;
        IDatabase database;
        string DefaultKey { get; set; }

        [Serializable]
        class CacheObject<T>
        {
            public int ExpireTime { get; set; }
            public bool ForceOutofDate { get; set; }
            public T Value { get; set; }
            
        }

        public Redis()
        {
            this.address = ConfigurationManager.AppSettings["RedisServer"] ?? "127.0.0.1:6379";

            if (this.address == null || string.IsNullOrWhiteSpace(this.address.ToString()))
                throw new ApplicationException("配置文件中未找到RedisServer的有效配置");
            connectionMultiplexer = ConnectionMultiplexer.Connect(address);
            database = connectionMultiplexer.GetDatabase();
            DefaultKey = ConfigurationManager.AppSettings["Redis.DefaultKey"] ?? "DefaultKey";
        }

        /// <summary>
        /// 连接超时设置
        /// </summary>
        public int TimeOut
        {
            get
            {
                return Default_Timeout;
            }
            set
            {
                Default_Timeout = value;
            }
        }

        public object Get(string key)
        {
            return Get<object>(key);
        }

        public T Get<T>(string key)
        {
            try
            {
                DateTime begin = DateTime.Now;
                var cacheValue = database.StringGet(key);
                DateTime endCache = DateTime.Now;
                var value = default(T);
                if (!cacheValue.IsNull)
                {
                    //var cacheObject = Deserialize<CacheObject<T>>(cacheValue);
                    //if (!cacheObject.ForceOutofDate)
                    //    database.KeyExpire(key, new TimeSpan(0, 0, cacheObject.ExpireTime));
                    //value = cacheObject.Value;
                    var cacheObject = Deserialize<T>(cacheValue);
                    value = cacheObject;
                }
                DateTime endJson = DateTime.Now;
                return value;
            }
            catch (Exception ex)
            {
                Log.writelog("Redis.Get", ex.Message, "redis.txt");
                database.KeyDelete(key, CommandFlags.HighPriority);
                return default(T);
            }
        }

        public void Insert(string key, string data)
        {
            database.StringSet(key, data);
        }
        public string GetString(string key)
        {
            return (string)database.StringGet(key);
        }

        public void Insert(string key, object data)
        {
            var jsonData = GetJsonData(data, TimeOut, false);
            database.StringSet(key, jsonData);
        }

        public void Insert(string key, object data, int cacheTime)
        {
            var timeSpan = TimeSpan.FromSeconds(cacheTime);
            var jsonData = GetJsonData(data, TimeOut, true);
            database.StringSet(key, jsonData, timeSpan);
        }

        public void Insert(string key, object data, DateTime cacheTime)
        {
            var timeSpan = cacheTime - DateTime.Now;
            var jsonData = GetJsonData(data, TimeOut, true);
            database.StringSet(key, jsonData, timeSpan);
        }

        public bool Insert<T>(string key, T data)
        {
            var jsonData = GetJsonData<T>(data, TimeOut, false);
            return database.StringSet(key, jsonData);
        }

        public void Insert<T>(string key, T data, int cacheTime)
        {
            var timeSpan = TimeSpan.FromSeconds(cacheTime);
            var jsonData = GetJsonData<T>(data, TimeOut, true);
            database.StringSet(key, jsonData, timeSpan);
        }

        public void Insert<T>(string key, T data, DateTime cacheTime)
        {
            var timeSpan = cacheTime - DateTime.Now;
            var jsonData = GetJsonData<T>(data, TimeOut, true);
            database.StringSet(key, jsonData, timeSpan);
        }

        public long StringIncrement(string key)
        {
            return database.StringIncrement(key);
        }

        byte[] GetJsonData(object data, int cacheTime, bool forceOutOfDate)
        {
            //var cacheObject = new CacheObject<object>() { Value = data, ExpireTime = cacheTime, ForceOutofDate = forceOutOfDate };
            //return Serialize(cacheObject);//序列化对象
            return Serialize(data);//序列化对象
        }

        byte[] GetJsonData<T>(T data, int cacheTime, bool forceOutOfDate)
        {
            //var cacheObject = new CacheObject<T>() { Value = data, ExpireTime = cacheTime, ForceOutofDate = forceOutOfDate };
            //return Serialize(cacheObject);//序列化对象
            return Serialize(data);//序列化对象
        }
        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="key"></param>
        public void Remove(string key)
        {
            database.KeyDelete(key, CommandFlags.HighPriority);
        }

        /// <summary>
        /// 判断key是否存在
        /// </summary>
        public bool Exists(string key)
        {
            return database.KeyExists(key);
        }

        #region List 操作

        /// <summary>
        /// 添加 Key 的前缀
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        private static string AddKeyPrefix(string key)
        {
            return key;
        }

        /// <summary>
        /// 移除并返回存储在该键列表的第一个元素
        /// </summary>
        /// <param name="redisKey"></param>
        /// <returns></returns>
        public string ListLeftPop(string redisKey)
        {
            redisKey = AddKeyPrefix(redisKey);
            return database.ListLeftPop(redisKey);
        }

        /// <summary>
        /// 移除并返回存储在该键列表的最后一个元素
        /// </summary>
        /// <param name="redisKey"></param>
        /// <returns></returns>
        public string ListRightPop(string redisKey)
        {
            redisKey = AddKeyPrefix(redisKey);
            return database.ListRightPop(redisKey);
        }

        /// <summary>
        /// 移除列表指定键上与该值相同的元素
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="redisValue"></param>
        /// <returns></returns>
        public long ListRemove(string redisKey, string redisValue)
        {
            redisKey = AddKeyPrefix(redisKey);
            return database.ListRemove(redisKey, redisValue);
        }

        /// <summary>
        /// 在列表尾部插入值。如果键不存在,先创建再插入值
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="redisValue"></param>
        /// <returns></returns>
        public long ListRightPush(string redisKey, string redisValue)
        {
            redisKey = AddKeyPrefix(redisKey);
            return database.ListRightPush(redisKey, redisValue);
        }

        /// <summary>
        /// 在列表头部插入值。如果键不存在,先创建再插入值
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="redisValue"></param>
        /// <returns></returns>
        public long ListLeftPush(string redisKey, string redisValue)
        {
            redisKey = AddKeyPrefix(redisKey);
            return database.ListLeftPush(redisKey, redisValue);
        }

        /// <summary>
        /// 返回列表上该键的长度,如果不存在,返回 0
        /// </summary>
        /// <param name="redisKey"></param>
        /// <returns></returns>
        public long ListLength(string redisKey)
        {
            redisKey = AddKeyPrefix(redisKey);
            return database.ListLength(redisKey);
        }

        /// <summary>
        /// 返回在该列表上键所对应的元素
        /// </summary>
        /// <param name="redisKey"></param>
        /// <returns></returns>
        public IEnumerable<RedisValue> ListRange(string redisKey)
        {
            redisKey = AddKeyPrefix(redisKey);
            return database.ListRange(redisKey);
        }

        /// <summary>
        /// 移除并返回存储在该键列表的第一个元素
        /// </summary>
        /// <param name="redisKey"></param>
        /// <returns></returns>
        public T ListLeftPop<T>(string redisKey)
        {
            redisKey = AddKeyPrefix(redisKey);
            return Deserialize<T>(database.ListLeftPop(redisKey));
        }

        /// <summary>
        /// 移除并返回存储在该键列表的最后一个元素
        /// </summary>
        /// <param name="redisKey"></param>
        /// <returns></returns>
        public T ListRightPop<T>(string redisKey)
        {
            redisKey = AddKeyPrefix(redisKey);
            return Deserialize<T>(database.ListRightPop(redisKey));
        }

        /// <summary>
        /// 在列表尾部插入值。如果键不存在,先创建再插入值
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="redisValue"></param>
        /// <returns></returns>
        public long ListRightPush<T>(string redisKey, T redisValue)
        {
            redisKey = AddKeyPrefix(redisKey);
            return database.ListRightPush(redisKey, Serialize(redisValue));
        }

        /// <summary>
        /// 在列表头部插入值。如果键不存在,先创建再插入值
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="redisValue"></param>
        /// <returns></returns>
        public long ListLeftPush<T>(string redisKey, T redisValue)
        {
            redisKey = AddKeyPrefix(redisKey);
            return database.ListLeftPush(redisKey, Serialize(redisValue));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="redisValue"></param>
        /// <returns></returns>
        public string ListGetByIndex(string redisKey, long index)
        {
            redisKey = AddKeyPrefix(redisKey);
            return database.ListGetByIndex(redisKey, index);
        }

        #region List-async

        /// <summary>
        /// 移除并返回存储在该键列表的第一个元素
        /// </summary>
        /// <param name="redisKey"></param>
        /// <returns></returns>
        public async Task<string> ListLeftPopAsync(string redisKey)
        {
            redisKey = AddKeyPrefix(redisKey);
            return await database.ListLeftPopAsync(redisKey);
        }

        /// <summary>
        /// 移除并返回存储在该键列表的最后一个元素
        /// </summary>
        /// <param name="redisKey"></param>
        /// <returns></returns>
        public async Task<string> ListRightPopAsync(string redisKey)
        {
            redisKey = AddKeyPrefix(redisKey);
            return await database.ListRightPopAsync(redisKey);
        }

        /// <summary>
        /// 移除列表指定键上与该值相同的元素
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="redisValue"></param>
        /// <returns></returns>
        public async Task<long> ListRemoveAsync(string redisKey, string redisValue)
        {
            redisKey = AddKeyPrefix(redisKey);
            return await database.ListRemoveAsync(redisKey, redisValue);
        }

        /// <summary>
        /// 在列表尾部插入值。如果键不存在,先创建再插入值
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="redisValue"></param>
        /// <returns></returns>
        public async Task<long> ListRightPushAsync(string redisKey, string redisValue)
        {
            redisKey = AddKeyPrefix(redisKey);
            return await database.ListRightPushAsync(redisKey, redisValue);
        }

        /// <summary>
        /// 在列表头部插入值。如果键不存在,先创建再插入值
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="redisValue"></param>
        /// <returns></returns>
        public async Task<long> ListLeftPushAsync(string redisKey, string redisValue)
        {
            redisKey = AddKeyPrefix(redisKey);
            return await database.ListLeftPushAsync(redisKey, redisValue);
        }

        /// <summary>
        /// 返回列表上该键的长度,如果不存在,返回 0
        /// </summary>
        /// <param name="redisKey"></param>
        /// <returns></returns>
        public async Task<long> ListLengthAsync(string redisKey)
        {
            redisKey = AddKeyPrefix(redisKey);
            return await database.ListLengthAsync(redisKey);
        }

        /// <summary>
        /// 返回在该列表上键所对应的元素
        /// </summary>
        /// <param name="redisKey"></param>
        /// <returns></returns>
        public async Task<IEnumerable<RedisValue>> ListRangeAsync(string redisKey)
        {
            redisKey = AddKeyPrefix(redisKey);
            return await database.ListRangeAsync(redisKey);
        }

        /// <summary>
        /// 移除并返回存储在该键列表的第一个元素
        /// </summary>
        /// <param name="redisKey"></param>
        /// <returns></returns>
        public async Task<T> ListLeftPopAsync<T>(string redisKey)
        {
            redisKey = AddKeyPrefix(redisKey);
            return Deserialize<T>(await database.ListLeftPopAsync(redisKey));
        }

        /// <summary>
        /// 移除并返回存储在该键列表的最后一个元素
        /// </summary>
        /// <param name="redisKey"></param>
        /// <returns></returns>
        public async Task<T> ListRightPopAsync<T>(string redisKey)
        {
            redisKey = AddKeyPrefix(redisKey);
            return Deserialize<T>(await database.ListRightPopAsync(redisKey));
        }

        /// <summary>
        /// 在列表尾部插入值。如果键不存在,先创建再插入值
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="redisValue"></param>
        /// <returns></returns>
        public async Task<long> ListRightPushAsync<T>(string redisKey, T redisValue)
        {
            redisKey = AddKeyPrefix(redisKey);
            return await database.ListRightPushAsync(redisKey, Serialize(redisValue));
        }

        /// <summary>
        /// 在列表头部插入值。如果键不存在,先创建再插入值
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="redisValue"></param>
        /// <returns></returns>
        public async Task<long> ListLeftPushAsync<T>(string redisKey, T redisValue)
        {
            redisKey = AddKeyPrefix(redisKey);
            return await database.ListLeftPushAsync(redisKey, Serialize(redisValue));
        }

        #endregion List-async

        #endregion List 操作

        #region Hash 操作

        /// <summary>
        /// 判断该字段是否存在 hash 中
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        public bool HashExists(string redisKey, string hashField)
        {
            redisKey = AddKeyPrefix(redisKey);
            return database.HashExists(redisKey, hashField);
        }

        /// <summary>
        /// 从 hash 中移除指定字段
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        public bool HashDelete(string redisKey, string hashField)
        {
            redisKey = AddKeyPrefix(redisKey);
            return database.HashDelete(redisKey, hashField);
        }

        /// <summary>
        /// 从 hash 中移除指定字段
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        public long HashDelete(string redisKey, IEnumerable<RedisValue> hashField)
        {
            redisKey = AddKeyPrefix(redisKey);
            return database.HashDelete(redisKey, hashField.ToArray());
        }

        /// <summary>
        /// 在 hash 设定值
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool HashSet(string redisKey, string hashField, string value)
        {
            redisKey = AddKeyPrefix(redisKey);
            return database.HashSet(redisKey, hashField, value);
        }

        /// <summary>
        /// 在 hash 设定值
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool HashSet(string redisKey, string hashField, long value)
        {
            redisKey = AddKeyPrefix(redisKey);
            return database.HashSet(redisKey, hashField, value);
        }

        /// <summary>
        /// 在 hash 中设定值
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashFields"></param>
        public void HashSet(string redisKey, IEnumerable<HashEntry> hashFields)
        {
            redisKey = AddKeyPrefix(redisKey);
            database.HashSet(redisKey, hashFields.ToArray());
        }

        /// <summary>
        /// 在 hash 中获取值
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        public object HashGet(string redisKey, string hashField)
        {
            redisKey = AddKeyPrefix(redisKey);
            return database.HashGet(redisKey, hashField);
        }

        /// <summary>
        /// 在 hash 中获取值
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public RedisValue[] HashGet(string redisKey, RedisValue[] hashField, string value)
        {
            redisKey = AddKeyPrefix(redisKey);
            return database.HashGet(redisKey, hashField);
        }

        /// <summary>
        /// 从 hash 返回所有的字段值
        /// </summary>
        /// <param name="redisKey"></param>
        /// <returns></returns>
        public IEnumerable<RedisValue> HashKeys(string redisKey)
        {
            redisKey = AddKeyPrefix(redisKey);
            return database.HashKeys(redisKey);
        }

        /// <summary>
        /// 返回 hash 中的所有值
        /// </summary>
        /// <param name="redisKey"></param>
        /// <returns></returns>
        public RedisValue[] HashValues(string redisKey)
        {
            redisKey = AddKeyPrefix(redisKey);
            return database.HashValues(redisKey);
        }

        /// <summary>
        /// 在 hash 设定值(序列化)
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool HashSet<T>(string redisKey, string hashField, T value)
        {
            redisKey = AddKeyPrefix(redisKey);
            var json = YChain.Framework.Core.Serializers.JsonSerializer.Serialize(value);
            return database.HashSet(redisKey, hashField, json);
            //RedisValue obj = getobj(value);
            //return database.HashSet(redisKey, hashField, obj);
        }

        public long SortedSetLength(string redisKey)
        {
            redisKey = AddKeyPrefix(redisKey);
            return database.SortedSetLength(redisKey);
        }

        public bool SortedSetAdd<T>(string redisKey, T member, double score)
        {
            redisKey = AddKeyPrefix(redisKey);
            var json = YChain.Framework.Core.Serializers.JsonSerializer.Serialize(member);
            return database.SortedSetAdd(redisKey, json, score, CommandFlags.None);
        }

        public bool SortedSetRemove<T>(string redisKey, T member)
        {
            redisKey = AddKeyPrefix(redisKey);
            var json = YChain.Framework.Core.Serializers.JsonSerializer.Serialize(member);
            return database.SortedSetRemove(redisKey, json);
        }

        public List<T> SortedSetRangeByScore<T>(string redisKey, double start, double stop)
        {
            redisKey = AddKeyPrefix(redisKey);
            var hashVals = database.SortedSetRangeByScore(redisKey, start, stop, Exclude.None, Order.Descending);

            List<T> list = new List<T>();
            foreach (var item in hashVals)
            {
                list.Add(YChain.Framework.Core.Serializers.JsonSerializer.Deserialize<T>(item.ToString()));
            }
            return list;
        }

        public List<T> SortedSetRangeByRank<T>(string redisKey, long start, long stop)
        {
            redisKey = AddKeyPrefix(redisKey);
            var hashVals = database.SortedSetRangeByRank(redisKey, start, stop, Order.Descending);

            List<T> list = new List<T>();
            foreach (var item in hashVals)
            {
                list.Add(YChain.Framework.Core.Serializers.JsonSerializer.Deserialize<T>(item.ToString()));
            }
            return list;
        }

        public RedisValue getobj(object value)
        {
            return (RedisValue)value;
        }

        public object getobj(RedisValue value)
        {
            return value;
        }

        /// <summary>
        /// 在 hash 中获取值(反序列化)
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        public T HashGet<T>(string redisKey, string hashField)
        {
            try
            {
                redisKey = AddKeyPrefix(redisKey);
                var t = database.HashGet(redisKey, hashField);
                string str = t.ToString();
                return YChain.Framework.Core.Serializers.JsonSerializer.Deserialize<T>(str);
            }
            catch(Exception ex)
            {
                return default(T);
            }
            //return Deserialize<T>(database.HashGet(redisKey, hashField));
            //RedisValue obj = database.HashGet(redisKey, hashField);
            //return (T)getobj(obj);
        }

        /// <summary>
        /// 在 hash 中获取值
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        public string HashGetString(string redisKey, string hashField)
        {
            try
            {
                redisKey = AddKeyPrefix(redisKey);
                var t = database.HashGet(redisKey, hashField);
                string str = t.ToString();
                return str;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        /// <summary>  
        /// 一个有问题的迭代器,可以便利hash key的全部元素  
        /// </summary>  
        /// <typeparam name="T"></typeparam>  
        /// <param name="key"></param>  
        /// <param name="pattern"></param>  
        /// <param name="pageSize"></param>  
        /// <returns></returns>  
        public List<T> HashScan<T>(string key, int pageSize, int pageOffset)
        {
            List<T> list = new List<T>();
            var hashVals = database.HashScan(key, pageSize, 0, pageOffset).ToList();
            foreach (var item in hashVals)
            {
                list.Add(YChain.Framework.Core.Serializers.JsonSerializer.Deserialize<T>(item.Value));
            }
            return list;
        }

        #region async

        /// <summary>
        /// 判断该字段是否存在 hash 中
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        public async Task<bool> HashExistsAsync(string redisKey, string hashField)
        {
            redisKey = AddKeyPrefix(redisKey);
            return await database.HashExistsAsync(redisKey, hashField);
        }

        /// <summary>
        /// 从 hash 中移除指定字段
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        public async Task<bool> HashDeleteAsync(string redisKey, string hashField)
        {
            redisKey = AddKeyPrefix(redisKey);
            return await database.HashDeleteAsync(redisKey, hashField);
        }

        /// <summary>
        /// 从 hash 中移除指定字段
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        public async Task<long> HashDeleteAsync(string redisKey, IEnumerable<RedisValue> hashField)
        {
            redisKey = AddKeyPrefix(redisKey);
            return await database.HashDeleteAsync(redisKey, hashField.ToArray());
        }

        /// <summary>
        /// 在 hash 设定值
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public async Task<bool> HashSetAsync(string redisKey, string hashField, string value)
        {
            redisKey = AddKeyPrefix(redisKey);
            return await database.HashSetAsync(redisKey, hashField, value);
        }

        /// <summary>
        /// 在 hash 中设定值
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashFields"></param>
        public async Task HashSetAsync(string redisKey, IEnumerable<HashEntry> hashFields)
        {
            redisKey = AddKeyPrefix(redisKey);
            await database.HashSetAsync(redisKey, hashFields.ToArray());
        }

        /// <summary>
        /// 在 hash 中获取值
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        public async Task<RedisValue> HashGetAsync(string redisKey, string hashField)
        {
            redisKey = AddKeyPrefix(redisKey);
            return await database.HashGetAsync(redisKey, hashField);
        }

        /// <summary>
        /// 在 hash 中获取值
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public async Task<IEnumerable<RedisValue>> HashGetAsync(string redisKey, RedisValue[] hashField, string value)
        {
            redisKey = AddKeyPrefix(redisKey);
            return await database.HashGetAsync(redisKey, hashField);
        }

        /// <summary>
        /// 从 hash 返回所有的字段值
        /// </summary>
        /// <param name="redisKey"></param>
        /// <returns></returns>
        public async Task<IEnumerable<RedisValue>> HashKeysAsync(string redisKey)
        {
            redisKey = AddKeyPrefix(redisKey);
            return await database.HashKeysAsync(redisKey);
        }

        /// <summary>
        /// 返回 hash 中的所有值
        /// </summary>
        /// <param name="redisKey"></param>
        /// <returns></returns>
        public async Task<IEnumerable<RedisValue>> HashValuesAsync(string redisKey)
        {
            redisKey = AddKeyPrefix(redisKey);
            return await database.HashValuesAsync(redisKey);
        }

        /// <summary>
        /// 在 hash 设定值(序列化)
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public async Task<bool> HashSetAsync<T>(string redisKey, string hashField, T value)
        {
            redisKey = AddKeyPrefix(redisKey);
            var json = Serialize(value);
            return await database.HashSetAsync(redisKey, hashField, json);
        }

        /// <summary>
        /// 在 hash 中获取值(反序列化)
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        public async Task<T> HashGetAsync<T>(string redisKey, string hashField)
        {
            redisKey = AddKeyPrefix(redisKey);
            return Deserialize<T>(await database.HashGetAsync(redisKey, hashField));
        }

        #endregion async

        #endregion Hash 操作

        /// <summary>
        /// 序列化
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        private static byte[] Serialize(object obj)
        {
            if (obj == null)
                return null;

            var binaryFormatter = new BinaryFormatter();
            using (var memoryStream = new MemoryStream())
            {
                binaryFormatter.Serialize(memoryStream, obj);
                var data = memoryStream.ToArray();
                return data;
            }
        }

        /// <summary>
        /// 反序列化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <returns></returns>
        private static T Deserialize<T>(byte[] data)
        {
            if (data == null)
                return default(T);

            var binaryFormatter = new BinaryFormatter();
            using (var memoryStream = new MemoryStream(data))
            {
                var result = (T)binaryFormatter.Deserialize(memoryStream);
                return result;
            }
        }

        public bool LockTake(string redisKey, string redisValue, TimeSpan timeSpan)
        {
            return database.LockTake(redisKey, redisValue, timeSpan);
        }

        public bool LockRelease(string redisKey, string redisValue)
        {
            return database.LockRelease(redisKey, redisValue);
        }
    }
}
 

(2)ICache.cs

using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace YChain.SinDouGame.Services
{
    public interface ICache
    {
        /// <summary>
        /// 缓存过期时间
        /// </summary>
        int TimeOut { set; get; }
        /// <summary>
        /// 获得指定键的缓存值
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <returns>缓存值</returns>
        object Get(string key);
        /// <summary>
        /// 获得指定键的缓存值
        /// </summary>
        T Get<T>(string key);
        /// <summary>
        /// 从缓存中移除指定键的缓存值
        /// </summary>
        /// <param name="key">缓存键</param>
        void Remove(string key);
        /// <summary>
        /// 清空所有缓存对象
        /// </summary>
        //void Clear();
        /// <summary>
        /// 将指定键的对象添加到缓存中
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <param name="data">缓存值</param>
        void Insert(string key, object data);
        /// <summary>
        /// 将指定键的对象添加到缓存中
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <param name="data">缓存值</param>
        bool Insert<T>(string key, T data);
        /// <summary>
        /// 将指定键的对象添加到缓存中,并指定过期时间
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <param name="data">缓存值</param>
        /// <param name="cacheTime">缓存过期时间(秒钟)</param>
        void Insert(string key, object data, int cacheTime);

        /// <summary>
        /// 将指定键的对象添加到缓存中,并指定过期时间
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <param name="data">缓存值</param>
        /// <param name="cacheTime">缓存过期时间(秒钟)</param>
        void Insert<T>(string key, T data, int cacheTime);
        /// <summary>
        /// 将指定键的对象添加到缓存中,并指定过期时间
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <param name="data">缓存值</param>
        /// <param name="cacheTime">缓存过期时间</param>
        void Insert(string key, object data, DateTime cacheTime);
        /// <summary>
        /// 将指定键的对象添加到缓存中,并指定过期时间
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <param name="data">缓存值</param>
        /// <param name="cacheTime">缓存过期时间</param>
        void Insert<T>(string key, T data, DateTime cacheTime);
        /// <summary>
        /// 判断key是否存在
        /// </summary>
        bool Exists(string key);
        /// <summary>
        /// 值自加1
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        long StringIncrement(string key);

        long ListLeftPush(string redisKey, string redisValue);

        long ListRightPush(string redisKey, string redisValue);

        string ListRightPop(string redisKey);

        string ListLeftPop(string redisKey);

        T ListLeftPop<T>(string redisKey);

        T ListRightPop<T>(string redisKey);

        long ListRightPush<T>(string redisKey, T redisValue);

        long ListLeftPush<T>(string redisKey, T redisValue);

        long ListLength(string redisKey);

        string ListGetByIndex(string redisKey, long index);

        bool LockTake(string redisKey, string redisValue, TimeSpan cacheTime);

        bool LockRelease(string redisKey, string redisValue);

        void Insert(string key, string data);

        string GetString(string key);

        #region Hash 操作

        bool HashExists(string redisKey, string hashField);

        bool HashDelete(string redisKey, string hashField);

        bool HashSet(string redisKey, string hashField, string value);

        bool HashSet(string redisKey, string hashField, long value);

        bool HashSet<T>(string redisKey, string hashField, T value);

        T HashGet<T>(string redisKey, string hashField);

        string HashGetString(string redisKey, string hashField);

        object HashGet(string redisKey, string hashField);

        List<T> HashScan<T>(string key, int pageSize, int pageOffset);
        #endregion Hash 操作
        long SortedSetLength(string redisKey);

        bool SortedSetAdd<T>(string redisKey, T member, double score);

        bool SortedSetRemove<T>(string redisKey, T member);

        List<T> SortedSetRangeByScore<T>(string redisKey, double start, double stop);

        List<T> SortedSetRangeByRank<T>(string redisKey, long start, long stop);
    }
}
 

(3) RedisCache.cs

using StackExchange.Redis;
using System;
using System.Collections.Generic;

namespace YChain.SinDouGame.Services
{
    /// <summary>
    /// 缓存
    /// </summary>
    public static class RedisCache
    {
        private static object cacheLocker = new object();//缓存锁对象
        private static ICache cache = null;//缓存接口

        static RedisCache()
        {
            Load();
        }

        /// <summary>
        /// 加载缓存
        /// </summary>
        /// <exception cref=""></exception>
        private static void Load()
        {
            try
            {
                cache = new Redis();
            }
            catch (Exception ex)
            {
                //Log.Error(ex.Message);
            }
        }

        public static ICache GetCache()
        {
            return cache;
        }


        /// <summary>
        /// 缓存过期时间
        /// </summary>
        public static int TimeOut
        {
            get
            {
                return cache.TimeOut;
            }
            set
            {
                lock (cacheLocker)
                {
                    cache.TimeOut = value;
                }
            }
        }

        public static void Insert(string key, string data)
        {
            cache.Insert(key, data);
        }
        public static string GetString(string key)
        {
            return cache.GetString(key);
        }

        /// <summary>
        /// 获得指定键的缓存值
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <returns>缓存值</returns>
        public static object Get(string key)
        {
            if (string.IsNullOrWhiteSpace(key))
                return null;
            return cache.Get(key);
        }

        /// <summary>
        /// 获得指定键的缓存值
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <returns>缓存值</returns>
        public static T Get<T>(string key)
        {
            return cache.Get<T>(key);
        }

        /// <summary>
        /// 将指定键的对象添加到缓存中
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <param name="data">缓存值</param>
        public static void Insert(string key, object data)
        {
            if (string.IsNullOrWhiteSpace(key) || data == null)
                return;
            //lock (cacheLocker)
            {
                cache.Insert(key, data);
            }
        }
        /// <summary>
        /// 将指定键的对象添加到缓存中
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <param name="data">缓存值</param>
        public static bool Insert<T>(string key, T data)
        {
            if (string.IsNullOrWhiteSpace(key) || data == null)
                return false;
            //lock (cacheLocker)
            {
                return cache.Insert<T>(key, data);
            }
        }
        /// <summary>
        /// 将指定键的对象添加到缓存中,并指定过期时间
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <param name="data">缓存值</param>
        /// <param name="cacheTime">缓存过期时间(分钟)</param>
        public static void Insert(string key, object data, int cacheTime)
        {
            if (!string.IsNullOrWhiteSpace(key) && data != null)
            {
                //lock (cacheLocker)
                {
                    cache.Insert(key, data, cacheTime);
                }
            }
        }

        /// <summary>
        /// 将指定键的对象添加到缓存中,并指定过期时间
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <param name="data">缓存值</param>
        /// <param name="cacheTime">缓存过期时间(分钟)</param>
        public static void Insert<T>(string key, T data, int cacheTime)
        {
            if (!string.IsNullOrWhiteSpace(key) && data != null)
            {
                //lock (cacheLocker)
                {
                    cache.Insert<T>(key, data, cacheTime);
                }
            }
        }

        /// <summary>
        /// 将指定键的对象添加到缓存中,并指定过期时间
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <param name="data">缓存值</param>
        /// <param name="cacheTime">缓存过期时间</param>
        public static void Insert(string key, object data, DateTime cacheTime)
        {
            if (!string.IsNullOrWhiteSpace(key) && data != null)
            {
                //lock (cacheLocker)
                {
                    cache.Insert(key, data, cacheTime);
                }
            }
        }

        /// <summary>
        /// 将指定键的对象添加到缓存中,并指定过期时间
        /// </summary>
        /// <param name="key">缓存键</param>
        /// <param name="data">缓存值</param>
        /// <param name="cacheTime">缓存过期时间</param>
        public static void Insert<T>(string key, T data, DateTime cacheTime)
        {
            if (!string.IsNullOrWhiteSpace(key) && data != null)
            {
                //lock (cacheLocker)
                {
                    cache.Insert<T>(key, data, cacheTime);
                }
            }
        }

        /// <summary>
        /// 从缓存中移除指定键的缓存值
        /// </summary>
        /// <param name="key">缓存键</param>
        public static void Remove(string key)
        {
            if (string.IsNullOrWhiteSpace(key))
                return;
            lock (cacheLocker)
            {
                cache.Remove(key);
            }
        }

        /// <summary>
        /// 判断key是否存在
        /// </summary>
        public static bool Exists(string key)
        {
            return cache.Exists(key);
        }

        /// <summary>
        /// 值自加1
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static long StringIncrement(string key)
        {
            return cache.StringIncrement(key);
        }

        public static long ListLeftPush(string redisKey, string redisValue)
        {
            return cache.ListLeftPush(redisKey, redisValue);
        }

        public static long ListRightPush(string redisKey, string redisValue)
        {
            return cache.ListRightPush(redisKey, redisValue);
        }

        public static string ListRightPop(string redisKey)
        {
            return cache.ListRightPop(redisKey);
        }

        public static string ListLeftPop(string redisKey)
        {
            return cache.ListLeftPop(redisKey);
        }

        public static T ListLeftPop<T>(string redisKey)
        {
            return cache.ListLeftPop<T>(redisKey);
        }

        public static T ListRightPop<T>(string redisKey)
        {
            return cache.ListRightPop<T>(redisKey);
        }

        public static long ListRightPush<T>(string redisKey, T redisValue)
        {
            return cache.ListRightPush(redisKey, redisValue);
        }

        public static long ListLeftPush<T>(string redisKey, T redisValue)
        {
            return cache.ListLeftPush(redisKey, redisValue);
        }

        public static long ListLength(string redisKey)
        {
            return cache.ListLength(redisKey);
        }

        public static string ListGetByIndex(string redisKey, long index)
        {
            return cache.ListGetByIndex(redisKey, index);
        }

        public static bool HashSet<T>(string redisKey, string hashField, T value)
        {
            return cache.HashSet(redisKey, hashField, value);
        }

        public static T HashGet<T>(string redisKey, string hashField)
        {
            return cache.HashGet<T>(redisKey, hashField);
        }

        public static string HashGetString(string redisKey, string hashField)
        {
            return cache.HashGetString(redisKey, hashField);
        }

        public static List<T> HashScan<T>(string redisKey, int pageSize, int pageOffset)
        {
            return cache.HashScan<T>(redisKey, pageSize, pageOffset);
        }

        public static long SortedSetLength(string redisKey)
        {
            return cache.SortedSetLength(redisKey);
        }

        public static bool SortedSetAdd<T>(string redisKey, T member, double score)
        {
            return cache.SortedSetAdd(redisKey, member, score);
        }

        public static bool SortedSetRemove<T>(string redisKey, T member)
        {
            return cache.SortedSetRemove(redisKey, member);
        }

        public static List<T> SortedSetRangeByScore<T>(string redisKey, double start, double stop)
        {
            return cache.SortedSetRangeByScore<T>(redisKey, start, stop);
        }

        public static List<T> SortedSetRangeByRank<T>(string redisKey, long start, long stop)
        {
            return cache.SortedSetRangeByRank<T>(redisKey, start, stop);
        }

        public static bool LockTake(string redisKey, string redisValue, TimeSpan cacheTime)
        {
            return cache.LockTake(redisKey, redisValue, cacheTime);
        }

        public static bool LockRelease(string redisKey, string redisValue)
        {
            return cache.LockRelease(redisKey, redisValue);
        }

        public static bool HashExists(string redisKey, string hashField)
        {
            return cache.HashExists(redisKey, hashField);
        }

        public static bool HashDelete(string redisKey, string hashField)
        {
            return cache.HashDelete(redisKey, hashField);
        }

        public static bool HashSet(string redisKey, string hashField, string value)
        {
            return cache.HashSet(redisKey, hashField, value);
        }

        public static bool HashSet(string redisKey, string hashField, long value)
        {
            return cache.HashSet(redisKey, hashField, value);
        }

        public static long HashGet(string redisKey, string hashField)
        {
            RedisValue t = (RedisValue)cache.HashGet(redisKey, hashField);
            string str = t.ToString();
            return long.Parse(str);
        }
    }
}
 

3、调用Redis

在本例中我使用用户流水的id作为sort的权重,而流水id是不会重复的,这样就可以直接存取指定id或指定id范围内的流水数据

using StackExchange.Redis;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace YChain.SinDouGame.Services
{
    /// <summary>
    /// 缓存
    /// </summary>
    public class RedisCacheExtension
    {
        private static readonly object syncFlowRoot = new object();
        private static long maxflowId = -1;
        private static long maxOrderId = -1;
        private static long currentOrderId = -1;
        private static long maxGuessId = -1;
        private static long currentGuessId = -1;
        private static RedisValue Token = Environment.MachineName;

        ConcurrentDictionary<string, long> cdic = new ConcurrentDictionary<string, long>();
        public static Dictionary<string, long> idset = new Dictionary<string, long>();
  public static Dictionary<string, List<AccountFlowOperate>> userAccountFlow = new Dictionary<string, List<AccountFlowOperate>>();
        

          /// <summary>
        /// 插入流水
        /// </summary>
        /// <param name="username"></param>
        /// <param name="data"></param>
        /// <param name="dbContext"></param>
        /// <returns></returns>

public static object InsertAccountFlow(string username, AccountFlowOperate data, IDbContext dbContext)
        {
            if (data == null)
                return null;
            string key = username;

            bool has_insert_db = false;
            lock (syncFlowRoot)
            {
                if (data.Id > 0)
                    has_insert_db = true;
                data.CreatedTime = DateTime.Now;
                data.UpdatedTime = DateTime.Now;

                //生成插入的id,在redis中保存id,使用redis锁控制读写

                if (RedisCache.Exists("accountflow_recordid"))
                {
                    DateTime t1 = DateTime.Now;
                    DateTime t2 = t1.AddSeconds(5);
                    TimeSpan ts = t2 - t1;
                    if (RedisCache.LockTake("accountflowId_lock", Token, ts))
                    {
                        try
                        {

                            //自加1
                            data.Id = RedisCache.StringIncrement("accountflow_recordid");
                        }
                        catch (Exception ex)
                        {

                        }
                        finally
                        {
                            RedisCache.LockRelease("accountflowId_lock", Token);
                        }
                    }
                    else
                    {
                        RedisCache.LockRelease("accountflowId_lock", Token);
                    }
                }
                else
                {

                    var lastflow = dbContext.Set<AccountFlowOperate>().OrderByDescending(p => p.Id).Take(1).ToList();
                    if (lastflow.Count() > 0)
                    {
                        maxflowId = lastflow[0].Id;
                    }
                    else
                    {
                        maxflowId = 0;
                    }
                    DateTime t1 = DateTime.Now;
                    DateTime t2 = t1.AddSeconds(5);
                    TimeSpan ts = t2 - t1;
                    if (RedisCache.LockTake("accountflowId_lock", Token, ts))
                    {
                        if (RedisCache.Exists("accountflow_recordid"))
                        {
                            try
                            {
                                data.Id = RedisCache.StringIncrement("accountflow_recordid");
                            }
                            catch (Exception ex)
                            {

                            }
                            finally
                            {
                                RedisCache.LockRelease("accountflowId_lock", Token);
                            }
                        }
                        else
                        {
                            try
                            {
                                RedisCache.Insert("accountflow_recordid", maxflowId.ToString());
                                data.Id = RedisCache.StringIncrement("accountflow_recordid");
                            }
                            catch (Exception ex)
                            {

                            }
                            finally
                            {
                                RedisCache.LockRelease("accountflowId_lock", Token);
                            }
                        }
                    }
                }
                //data.Id = ++maxflowId;
            }
            #region redis_sort_set
            string redis_key = "sort_flow_" + username;
            if (RedisCache.Exists(redis_key))
            {

                //将流水id最为权重,存储在sortset中
                RedisCache.SortedSetAdd(redis_key, data, data.Id);
            }
            else
            {
                DateTime starttime = DateTime.Now.AddDays(-30);
                List<AccountFlowOperate> accountflowList = dbContext.Set<AccountFlowOperate>().Where(p => p.AccountName == username && p.CreatedTime > starttime).OrderByDescending(p => p.Id).Take(1000).ToList();
                foreach (var flow in accountflowList)
                {

                    //将流水id最为权重,存储在sortset中
                    RedisCache.SortedSetAdd(redis_key, flow, flow.Id);
                }
                if (has_insert_db == false)
                    RedisCache.SortedSetAdd(redis_key, data, data.Id);
            }
            #endregion
            return null;
        }

/// <summary>
        /// 获取用户的全部流水
        /// </summary>
        /// <param name="username"></param>
        /// <param name="dbContext"></param>
        /// <returns></returns>
        public static List<AccountFlowOperate> GetAccountFlow(string username, IDbContext dbContext)
        {
            #region redis_sort_set
            string redis_key = "sort_flow_" + username;
            if (RedisCache.Exists(redis_key))
            {

                //先获取数据的总长度
                long redis_length = RedisCache.SortedSetLength(redis_key);
                List<AccountFlowOperate> accountflowList = new List<AccountFlowOperate>();
                long current_length = 0;

                //再多次取数据,每次只取1000行,通过测试如果一次性读写太多数据,读写的速度太慢,而多次少量读取则会非常快
                while (current_length < redis_length)
                {
                    accountflowList.AddRange(RedisCache.SortedSetRangeByRank<AccountFlowOperate>(redis_key, current_length, current_length + 1000 - 1));
                    current_length += 1000;
                }
                return accountflowList;
            }
            else
            {
                DateTime starttime = DateTime.Now.AddDays(-30);
                List<AccountFlowOperate> accountflowList = dbContext.Set<AccountFlowOperate>().Where(p => p.AccountName == username && p.CreatedTime > starttime).OrderByDescending(p => p.Id).Take(1000).ToList();
                foreach (var flow in accountflowList)
                {
                    RedisCache.SortedSetAdd(redis_key, flow, flow.Id);
                }
                return accountflowList;
            }
            #endregion
        }

 

        /// <summary>
        /// 通过start 和 stop 控制分页获取流水数据
        /// </summary>
        /// <param name="username"></param>
        /// <param name="start"></param>
        /// <param name="stop"></param>
        /// <param name="dbContext"></param>
        /// <param name="flow_length"></param>
        /// <returns></returns>
        public static List<AccountFlowOperate> GetAccountFlow(string username, long start, long stop, IDbContext dbContext, ref long flow_length)
        {
            #region redis_sort_set
            string redis_key = "sort_flow_" + username;
            if (RedisCache.Exists(redis_key))
            {
                flow_length = RedisCache.SortedSetLength(redis_key);
                List<AccountFlowOperate> accountflowList = new List<AccountFlowOperate>();
                if (stop > flow_length)
                    stop = flow_length - 1;
                if (start > flow_length)
                    return accountflowList;
                accountflowList.AddRange(RedisCache.SortedSetRangeByRank<AccountFlowOperate>(redis_key, start, stop));
                return accountflowList;
            }
            else
            {
                DateTime starttime = DateTime.Now.AddDays(-30);
                List<AccountFlowOperate> accountflowList = dbContext.Set<AccountFlowOperate>().Where(p => p.AccountName == username && p.CreatedTime > starttime).OrderByDescending(p => p.Id).Take(1000).ToList();
                foreach (var flow in accountflowList)
                {
                    RedisCache.SortedSetAdd(redis_key, flow, flow.Id);
                }
                flow_length = accountflowList.Count();
                return RedisCache.SortedSetRangeByRank<AccountFlowOperate>(redis_key, start, stop);
            }
            #endregion
        }

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值