using FreeRedis;
using Masuit.Tools;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YuanXuan.IM.Infrastructure.Redis
{
public abstract class RedisHelper
{
private static RedisClient _instance;
///
/// redis实例
///
public static RedisClient Instance
{
get
{
if (_instance == null)
{
throw new Exception("使用前初始化redis静态访问类 RedisHelper.Initialization(new FreeRedis.RedisClient(\"127.0.0.1:6379,password=123,defaultDatabase=13,maxpoolsize=50,prefix=key前辍\"));");
}
return _instance;
}
}
public static void SetLoginToken(long userId, string token)
{
var key = "Login_Token";
Instance.HSet(key, userId.ToString(), token);
}
public static void DeleteLoginToken(long userId)
{
var key = "Login_Token";
Instance.HDel(key, userId.ToString());
}
///
/// 初始化redis静态访问类 RedisHelper.Initialization(new FreeRedis.RedisClient(\"127.0.0.1:6379,password=123,defaultDatabase=13,maxpoolsize=50,prefix=key前辍\"))
///
///
public static void Initialization(string connectionString)
{
_instance = new FreeRedis.RedisClient(connectionString)
{
Serialize = (x) => x.ToJsonString(),
Deserialize = (x, t) => JsonConvert.DeserializeObject(x, t),
};
}
internal static ThreadLocal rnd = new ThreadLocal(() => new Random());
///
/// 随机秒(防止所有key同一时间过期,雪崩)
///
/// 最小秒数
/// 最大秒数
///
public static int RandomExpired(int minTimeoutSeconds, int maxTimeoutSeconds) => rnd.Value.Next(minTimeoutSeconds, maxTimeoutSeconds);
///
/// 获取Redis分布式锁
///
/// 锁键
/// 锁值(建议使用GUID)
/// 过期时间(秒)
/// 是否获取成功
public static bool TryLock(string lockKey, string lockValue, int expireSeconds = 30)
{
return Instance.SetNx(lockKey, lockValue, expireSeconds);
}
///
/// 释放Redis分布式锁
///
/// 锁键
/// 锁值(必须与加锁时一致)
/// 是否释放成功
public static bool ReleaseLock(string lockKey, string lockValue)
{
// 使用Lua脚本确保原子性:只有当锁的值匹配时才删除
const string luaScript = @"
if redis.call('GET', KEYS[1]) == ARGV[1] then
return redis.call('DEL', KEYS[1])
else
return 0
end";
var result = Instance.Eval(luaScript, new[] { lockKey }, new[] { lockValue });
return (long)result == 1;
}
///
/// 延长Redis锁的过期时间
///
/// 锁键
/// 锁值
/// 新的过期时间(秒)
/// 是否续期成功
public static bool RenewLock(string lockKey, string lockValue, int expireSeconds)
{
// 使用Lua脚本确保原子性:只有当锁的值匹配时才更新过期时间
const string luaScript = @"
if redis.call('GET', KEYS[1]) == ARGV[1] then
return redis.call('EXPIRE', KEYS[1], ARGV[2])
else
return 0
end";
var result = Instance.Eval(luaScript, new[] { lockKey }, new[] { lockValue, expireSeconds.ToString() });
return (long)result == 1;
}
///
/// 异步设置键值对
///
/// 键
/// 值
/// 过期时间
///
public static async Task SetAsync(string key, object value, TimeSpan expiry)
{
await Instance.SetAsync(key, value, expiry);
}
///
/// 异步获取字符串值
///
/// 键
///
public static async Task GetStringAsync(string key)
{
return await Instance.GetAsync(key);
}
///
/// 异步删除键
///
/// 键
///
public static async Task DeleteAsync(string key)
{
await Instance.DelAsync(key);
}
///
/// 异步获取值
///
/// 类型
/// 键
///
public static async Task GetAsync(string key)
{
return await Instance.GetAsync(key);
}
///
/// 异步设置键值对(默认过期时间)
///
/// 键
/// 值
///
public static async Task SetAsync(string key, object value)
{
await Instance.SetAsync(key, value);
}
}
}