using Newtonsoft.Json; using StackExchange.Redis; using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Web; namespace WebAPI.Common { /// <summary> /// /// </summary> public class Redis : ICache { int Default_Timeout = 600;//默认超时时间(单位秒) string address; JsonSerializerSettings jsonConfig = new JsonSerializerSettings() { ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore, NullValueHandling = NullValueHandling.Ignore }; ConnectionMultiplexer connectionMultiplexer; IDatabase database; class CacheObject<T> { public int ExpireTime { get; set; } public bool ForceOutofDate { get; set; } public T Value { get; set; } } /// <summary> /// /// </summary> /// <param name="dbbase"></param> public Redis(int dbbase = 0) { this.address = this.address = ConfigurationManager.AppSettings["RedisHosts"]; if (this.address == null || string.IsNullOrWhiteSpace(this.address.ToString())) throw new ApplicationException("配置文件中未找到RedisServer的有效配置"); connectionMultiplexer = ConnectionMultiplexer.Connect(address); database = connectionMultiplexer.GetDatabase(dbbase); } /// <summary> /// 连接超时设置 /// </summary> public int TimeOut { get { return Default_Timeout; } set { Default_Timeout = value; } } /// <summary> /// /// </summary> /// <param name="key"></param> /// <returns></returns> public object Get(string key) { return Get<object>(key); } /// <summary> /// /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public T Get<T>(string key) { DateTime begin = DateTime.Now; var cacheValue = database.StringGet(key); DateTime endCache = DateTime.Now; var value = default(T); if (!cacheValue.IsNull) { var cacheObject = JsonConvert.DeserializeObject<CacheObject<T>>(cacheValue, jsonConfig); if (!cacheObject.ForceOutofDate) database.KeyExpire(key, new TimeSpan(0, 0, cacheObject.ExpireTime)); value = cacheObject.Value; } DateTime endJson = DateTime.Now; return value; } /// <summary> /// /// </summary> /// <param name="key"></param> /// <param name="data"></param> public void Insert(string key, object data) { var jsonData = GetJsonData(data, TimeOut, false); database.StringSet(key, jsonData); } /// <summary> /// /// </summary> /// <param name="key"></param> /// <param name="data"></param> /// <param name="cacheTime"></param> 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); } /// <summary> /// /// </summary> /// <param name="key"></param> /// <param name="data"></param> /// <param name="cacheTime"></param> 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); } /// <summary> /// /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="data"></param> public void Insert<T>(string key, T data) { var jsonData = GetJsonData<T>(data, TimeOut, false); database.StringSet(key, jsonData); } /// <summary> /// /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="data"></param> /// <param name="cacheTime"></param> 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); } /// <summary> /// /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="data"></param> /// <param name="cacheTime"></param> 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); } /// <summary> /// /// </summary> /// <param name="data"></param> /// <param name="cacheTime"></param> /// <param name="forceOutOfDate"></param> /// <returns></returns> string GetJsonData(object data, int cacheTime, bool forceOutOfDate) { var cacheObject = new CacheObject<object>() { Value = data, ExpireTime = cacheTime, ForceOutofDate = forceOutOfDate }; return JsonConvert.SerializeObject(cacheObject, jsonConfig);//序列化对象 } /// <summary> /// /// </summary> /// <typeparam name="T"></typeparam> /// <param name="data"></param> /// <param name="cacheTime"></param> /// <param name="forceOutOfDate"></param> /// <returns></returns> string GetJsonData<T>(T data, int cacheTime, bool forceOutOfDate) { var cacheObject = new CacheObject<T>() { Value = data, ExpireTime = cacheTime, ForceOutofDate = forceOutOfDate }; return JsonConvert.SerializeObject(cacheObject, jsonConfig);//序列化对象 } /// <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); } /// <summary> /// 右侧入队 /// </summary> /// <param name="queueName">队列名称</param> /// <param name="redisValue">值</param> /// <returns></returns> public long EnqueueListRightPush(RedisKey queueName, RedisValue redisValue) { return database.ListRightPush(queueName, redisValue); } /// <summary> /// 左侧入队 /// </summary> /// <param name="queueName">队列名称</param> /// <param name="redisvalue">队列值</param> /// <returns></returns> public long EnqueueListLeftPush(RedisKey queueName, RedisValue redisvalue) { return database.ListLeftPush(queueName, redisvalue); } /// <summary> /// 获取队列长度 /// </summary> /// <param name="queueName">队列名称</param> /// <returns></returns> public long EnqueueListLength(RedisKey queueName) { if (database.KeyExists(queueName)) { return database.ListLength(queueName); } else { return 0; } } /// <summary> /// 左侧出队 /// </summary> /// <param name="queueName"></param> /// <returns></returns> public string DequeueListPopLeft(RedisKey queueName) { int count = database.ListRange(queueName).Length; if (count > 0) { string redisValue = database.ListLeftPop(queueName); if (!string.IsNullOrEmpty(redisValue)) return redisValue; else return string.Empty; } else { return "-1"; throw new Exception($"队列{queueName}数据为零"); } } /// <summary> /// 右侧出队 /// </summary> public string DequeueListPopRight(RedisKey queueName) { int count = database.ListRange(queueName).Length; if (count > 0) { string redisValue = database.ListRightPop(queueName); if (!string.IsNullOrEmpty(redisValue)) return redisValue; else return string.Empty; } else { return "-1"; throw new Exception($"队列{queueName}数据为零"); } } /// <summary> /// 分布式加锁 /// </summary> /// <param name="key">键</param> /// <param name="data">值</param> /// <param name="seconds">过期时间</param> /// <returns></returns> public bool LockTake(string key, string data, TimeSpan seconds, int db = 0) { return database.LockTake(key, data, seconds); } /// <summary> /// 解锁 /// </summary> /// <param name="key">键</param> /// <param name="data">值</param> /// <returns></returns> public bool LockRelease(string key, string data, int db = -1) { return database.LockRelease(key, data); } } }