280 lines
8.0 KiB
C#
280 lines
8.0 KiB
C#
#region
|
||
|
||
using StackExchange.Redis;
|
||
using Web.Core.Common.Helper;
|
||
|
||
#endregion
|
||
|
||
namespace Web.Core.Common.Redis;
|
||
|
||
public class RedisCacheManager : IRedisCacheManager
|
||
{
|
||
private readonly string redisConnenctionString;
|
||
private readonly string DefaultKey; //默认的 Key 值(用来当作 RedisKey 的前缀)
|
||
public volatile ConnectionMultiplexer redisConnection;
|
||
private readonly IDatabase _db;
|
||
private readonly object redisConnectionLock = new();
|
||
|
||
public RedisCacheManager()
|
||
{
|
||
var redisConfiguration = AppSettings.GetConnectionString("Redis"); //获取连接字符串
|
||
var dbnum = AppSettings.GetValue("RedisInfo:DefaultDB", 15);
|
||
|
||
if (string.IsNullOrWhiteSpace(redisConfiguration))
|
||
{
|
||
throw new ArgumentException("redis config is empty", nameof(redisConfiguration));
|
||
}
|
||
|
||
redisConnenctionString = redisConfiguration;
|
||
redisConnection = GetRedisConnection();
|
||
_db = redisConnection.GetDatabase(dbnum);
|
||
DefaultKey = AppSettings.GetLogLevel("RedisInfo:DefaultKey");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 核心代码,获取连接实例
|
||
/// 通过双if 夹lock的方式,实现单例模式
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
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服务未启用,请开启该服务");
|
||
}
|
||
}
|
||
|
||
return redisConnection;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加 Key 的前缀
|
||
/// </summary>
|
||
/// <param name="key"></param>
|
||
/// <returns></returns>
|
||
private string AddKeyPrefix(string key)
|
||
{
|
||
return $"{DefaultKey}:{key}";
|
||
}
|
||
|
||
public void Clear()
|
||
{
|
||
foreach (var endPoint in GetRedisConnection().GetEndPoints())
|
||
{
|
||
var server = GetRedisConnection().GetServer(endPoint);
|
||
foreach (var key in server.Keys())
|
||
{
|
||
_db.KeyDelete(key);
|
||
}
|
||
}
|
||
}
|
||
|
||
public bool Get(string key)
|
||
{
|
||
return _db.KeyExists(AddKeyPrefix(key));
|
||
}
|
||
|
||
public string GetValue(string key)
|
||
{
|
||
return _db.StringGet(key);
|
||
}
|
||
|
||
public TEntity Get<TEntity>(string key)
|
||
{
|
||
var value = _db.StringGet(key);
|
||
if (value.HasValue)
|
||
{
|
||
//需要用的反序列化,将Redis存储的Byte[],进行反序列化
|
||
return SerializeHelper.Deserialize<TEntity>(value);
|
||
}
|
||
else
|
||
{
|
||
return default;
|
||
}
|
||
}
|
||
|
||
public void Remove(string key)
|
||
{
|
||
_db.KeyDelete(AddKeyPrefix(key));
|
||
}
|
||
|
||
public void Set(string key, object value, TimeSpan cacheTime)
|
||
{
|
||
if (value != null)
|
||
{
|
||
//序列化,将object值生成RedisValue
|
||
//_db.StringSet(AddKeyPrefix(key), SerializeHelper.Serialize(value), cacheTime);
|
||
_db.StringSet(key, SerializeHelper.Serialize(value), cacheTime);
|
||
}
|
||
}
|
||
|
||
public bool SetValue(string key, byte[] value)
|
||
{
|
||
return _db.StringSet(AddKeyPrefix(key), value, TimeSpan.FromSeconds(120));
|
||
}
|
||
|
||
public async Task ClearAsync()
|
||
{
|
||
foreach (var endPoint in GetRedisConnection().GetEndPoints())
|
||
{
|
||
var server = GetRedisConnection().GetServer(endPoint);
|
||
foreach (var key in server.Keys())
|
||
{
|
||
await _db.KeyDeleteAsync(key);
|
||
}
|
||
}
|
||
}
|
||
|
||
public async Task<bool> GetAsync(string key)
|
||
{
|
||
return await _db.KeyExistsAsync(AddKeyPrefix(key));
|
||
}
|
||
|
||
public async Task<string> GetValueAsync(string key)
|
||
{
|
||
return await _db.StringGetAsync(AddKeyPrefix(key));
|
||
}
|
||
|
||
public async Task<TEntity> GetAsync<TEntity>(string key)
|
||
{
|
||
var value = await _db.StringGetAsync(AddKeyPrefix(key));
|
||
if (value.HasValue)
|
||
{
|
||
//需要用的反序列化,将Redis存储的Byte[],进行反序列化
|
||
return SerializeHelper.Deserialize<TEntity>(value);
|
||
}
|
||
else
|
||
{
|
||
return default;
|
||
}
|
||
}
|
||
|
||
public async Task RemoveAsync(string key)
|
||
{
|
||
await _db.KeyDeleteAsync(AddKeyPrefix(key));
|
||
}
|
||
|
||
public async Task RemoveByKey(string key)
|
||
{
|
||
var redisResult = await _db.ScriptEvaluateAsync(LuaScript.Prepare(
|
||
//Redis的keys模糊查询:
|
||
" local res = redis.call('KEYS', @keypattern) " +
|
||
" return res "), new { @keypattern = AddKeyPrefix(key) });
|
||
|
||
if (!redisResult.IsNull)
|
||
{
|
||
var keys = (string[])redisResult;
|
||
foreach (var k in keys)
|
||
_db.KeyDelete(k);
|
||
}
|
||
}
|
||
|
||
public async Task SetAsync(string key, object value, TimeSpan cacheTime)
|
||
{
|
||
if (value != null)
|
||
{
|
||
//序列化,将object值生成RedisValue
|
||
await _db.StringSetAsync(AddKeyPrefix(key), SerializeHelper.Serialize(value), cacheTime);
|
||
}
|
||
}
|
||
|
||
public async Task<bool> SetValueAsync(string key, byte[] value)
|
||
{
|
||
return await _db.StringSetAsync(AddKeyPrefix(key), value, TimeSpan.FromSeconds(120));
|
||
}
|
||
|
||
#region set帮助
|
||
|
||
/// <summary>
|
||
/// Set新增
|
||
/// </summary>
|
||
/// <param name="redisKey"></param>
|
||
/// <param name="member"></param>
|
||
/// <returns></returns>
|
||
public bool SetAdd(string redisKey, string member,bool IgnorePrefix=false)
|
||
{
|
||
redisKey = IgnorePrefix?redisKey:AddKeyPrefix(redisKey);
|
||
return _db.SetAdd(redisKey, member);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Set新增
|
||
/// </summary>
|
||
/// <param name="redisKey"></param>
|
||
/// <param name="member"></param>
|
||
/// <returns></returns>
|
||
public async Task<bool> SetAddAsync(string redisKey, string member,bool IgnorePrefix=false)
|
||
{
|
||
redisKey = IgnorePrefix?redisKey:AddKeyPrefix(redisKey);
|
||
return await _db.SetAddAsync(redisKey, member);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Set判断元素是否包含
|
||
/// </summary>
|
||
/// <param name="redisKey"></param>
|
||
/// <param name="member"></param>
|
||
/// <returns></returns>
|
||
public bool SetContains(string redisKey, string member,bool IgnorePrefix=false)
|
||
{
|
||
redisKey = IgnorePrefix?redisKey:AddKeyPrefix(redisKey);
|
||
return _db.SetContains(redisKey, member);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Set判断元素是否包含
|
||
/// </summary>
|
||
/// <param name="redisKey"></param>
|
||
/// <param name="member"></param>
|
||
/// <returns></returns>
|
||
public async Task<bool> SetContainsAsync(string redisKey, string member,bool IgnorePrefix=false)
|
||
{
|
||
redisKey = IgnorePrefix?redisKey:AddKeyPrefix(redisKey);
|
||
return await _db.SetContainsAsync(redisKey, member);
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Set移除元素
|
||
/// </summary>
|
||
/// <param name="redisKey"></param>
|
||
/// <param name="member"></param>
|
||
/// <returns></returns>
|
||
public bool SetRemove(string redisKey, string member,bool IgnorePrefix=false)
|
||
{
|
||
redisKey = IgnorePrefix?redisKey:AddKeyPrefix(redisKey);
|
||
return _db.SetRemove(redisKey, member);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Set移除元素
|
||
/// </summary>
|
||
/// <param name="redisKey"></param>
|
||
/// <param name="member"></param>
|
||
/// <returns></returns>
|
||
public async Task<bool> SetRemoveAsync(string redisKey, string member,bool IgnorePrefix=false)
|
||
{
|
||
redisKey = IgnorePrefix?redisKey:AddKeyPrefix(redisKey);
|
||
return await _db.SetRemoveAsync(redisKey, member);
|
||
}
|
||
#endregion
|
||
} |