using StackExchange.Redis; using Znyc.CloudCar.Configuration; using Znyc.CloudCar.Utility.Extensions; namespace Znyc.CloudCar.Auth.Manual { public class RedisCacheManager : IManualCacheManager { private readonly string _redisConnenctionString; public volatile ConnectionMultiplexer RedisConnection; private readonly object _redisConnectionLock = new object(); public RedisCacheManager() { string redisConfiguration = AppSettingsConstVars.RedisConfigConnectionString;//获取连接字符串 if (string.IsNullOrWhiteSpace(redisConfiguration)) { throw new ArgumentException("redis config is empty", nameof(redisConfiguration)); } _redisConnenctionString = redisConfiguration; RedisConnection = GetRedisConnection(); } /// /// 核心代码,获取连接实例 /// 通过双if 夹lock的方式,实现单例模式 /// /// private ConnectionMultiplexer GetRedisConnection() { //如果已经连接实例,直接返回 if (RedisConnection != null && RedisConnection.IsConnected) { return RedisConnection; } //加锁,防止异步编程中,出现单例无效的问题 lock (_redisConnectionLock) { if (RedisConnection != null) { //释放redis连接 RedisConnection.Dispose(); } try { RedisConnection = ConnectionMultiplexer.Connect(_redisConnenctionString); } catch (Exception) { throw new Exception("Redis服务未启用,请开启该服务,并且请注意端口号,Redis默认使用6379端口号。"); } } return RedisConnection; } /// /// 判断key是否存在 /// /// /// public bool Exists(string key) { return RedisConnection.GetDatabase().KeyExists(key); } /// /// 添加缓存 /// /// /// 缓存Key /// 缓存Value /// 缓存时间 /// public bool Set(string key, object value, int expiresIn = 0) { if (value != null) { //序列化,将object值生成RedisValue if (expiresIn > 0) { return RedisConnection.GetDatabase().StringSet(key, SerializeExtensions.Serialize(value), TimeSpan.FromMinutes(expiresIn)); } else { return RedisConnection.GetDatabase().StringSet(key, SerializeExtensions.Serialize(value)); } } return false; } /// /// 删除缓存 /// /// 缓存Key /// public void Remove(string key) { RedisConnection.GetDatabase().KeyDelete(key); } /// /// 批量删除缓存 /// /// 缓存Key集合 /// public void RemoveAll(IEnumerable keys) { foreach (var key in keys) { RedisConnection.GetDatabase().KeyDelete(key); } } /// /// 获取缓存对象 /// /// 缓存Key /// public T Get(string key) { var value = RedisConnection.GetDatabase().StringGet(key); if (value.HasValue) { //需要用的反序列化,将Redis存储的Byte[],进行反序列化 return SerializeExtensions.Deserialize(value); } return default; } public object Get(string key) { return RedisConnection.GetDatabase().StringGet(key); } public IDictionary GetAll(IEnumerable keys) { if (keys == null) throw new ArgumentNullException(nameof(keys)); var dict = new Dictionary(); keys.ToList().ForEach(item => dict.Add(item, RedisConnection.GetDatabase().StringGet(item))); return dict; } /// /// 删除所有缓存 /// public void RemoveCacheAll() { foreach (var endPoint in GetRedisConnection().GetEndPoints()) { var server = GetRedisConnection().GetServer(endPoint); foreach (var key in server.Keys()) { RedisConnection.GetDatabase().KeyDelete(key); } } } /// /// 删除匹配到的缓存 /// /// public void RemoveCacheRegex(string pattern) { var script = "return redis.call('keys',@pattern)"; var prepared = LuaScript.Prepare(script); var redisResult = RedisConnection.GetDatabase().ScriptEvaluate(prepared, new { pattern }); if (!redisResult.IsNull) { RedisConnection.GetDatabase().KeyDelete((RedisKey[])redisResult); //删除一组key } } /// /// 搜索匹配到的缓存 /// /// /// public IList SearchCacheRegex(string pattern) { var list = new List(); var script = "return redis.call('keys',@pattern)"; var prepared = LuaScript.Prepare(script); var redisResult = RedisConnection.GetDatabase().ScriptEvaluate(prepared, new { pattern }); if (!redisResult.IsNull) { foreach (var key in (RedisKey[])redisResult) { list.Add(RedisConnection.GetDatabase().StringGet(key)); } } return list; } /// /// 添加缓存 /// /// 缓存key /// 缓存Value /// 缓存时长(分钟) /// public bool Set(string key, string value, int expiresIn = 0) { if (value != null) { if (expiresIn > 0) { return RedisConnection.GetDatabase().StringSet(key, SerializeExtensions.Serialize(value), TimeSpan.FromMinutes(expiresIn)); } else { return RedisConnection.GetDatabase().StringSet(key, SerializeExtensions.Serialize(value)); } } return false; } } }