CSharp.Template/YuanXuan.IM.Infrastructure/Redis/RedisHelper.cs

173 lines
6.1 KiB
C#
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
/// <summary>
/// redis实例
/// </summary>
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());
}
/// <summary>
/// 初始化redis静态访问类 RedisHelper.Initialization(new FreeRedis.RedisClient(\"127.0.0.1:6379,password=123,defaultDatabase=13,maxpoolsize=50,prefix=key前辍\"))
/// </summary>
/// <param name="redisClient"></param>
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<Random> rnd = new ThreadLocal<Random>(() => new Random());
/// <summary>
/// 随机秒防止所有key同一时间过期雪崩
/// </summary>
/// <param name="minTimeoutSeconds">最小秒数</param>
/// <param name="maxTimeoutSeconds">最大秒数</param>
/// <returns></returns>
public static int RandomExpired(int minTimeoutSeconds, int maxTimeoutSeconds) => rnd.Value.Next(minTimeoutSeconds, maxTimeoutSeconds);
/// <summary>
/// 获取Redis分布式锁
/// </summary>
/// <param name="lockKey">锁键</param>
/// <param name="lockValue">锁值建议使用GUID</param>
/// <param name="expireSeconds">过期时间(秒)</param>
/// <returns>是否获取成功</returns>
public static bool TryLock(string lockKey, string lockValue, int expireSeconds = 30)
{
return Instance.SetNx(lockKey, lockValue, expireSeconds);
}
/// <summary>
/// 释放Redis分布式锁
/// </summary>
/// <param name="lockKey">锁键</param>
/// <param name="lockValue">锁值(必须与加锁时一致)</param>
/// <returns>是否释放成功</returns>
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;
}
/// <summary>
/// 延长Redis锁的过期时间
/// </summary>
/// <param name="lockKey">锁键</param>
/// <param name="lockValue">锁值</param>
/// <param name="expireSeconds">新的过期时间(秒)</param>
/// <returns>是否续期成功</returns>
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;
}
/// <summary>
/// 异步设置键值对
/// </summary>
/// <param name="key">键</param>
/// <param name="value">值</param>
/// <param name="expiry">过期时间</param>
/// <returns></returns>
public static async Task SetAsync(string key, object value, TimeSpan expiry)
{
await Instance.SetAsync(key, value, expiry);
}
/// <summary>
/// 异步获取字符串值
/// </summary>
/// <param name="key">键</param>
/// <returns></returns>
public static async Task<string> GetStringAsync(string key)
{
return await Instance.GetAsync<string>(key);
}
/// <summary>
/// 异步删除键
/// </summary>
/// <param name="key">键</param>
/// <returns></returns>
public static async Task DeleteAsync(string key)
{
await Instance.DelAsync(key);
}
/// <summary>
/// 异步获取值
/// </summary>
/// <typeparam name="T">类型</typeparam>
/// <param name="key">键</param>
/// <returns></returns>
public static async Task<T> GetAsync<T>(string key)
{
return await Instance.GetAsync<T>(key);
}
/// <summary>
/// 异步设置键值对(默认过期时间)
/// </summary>
/// <param name="key">键</param>
/// <param name="value">值</param>
/// <returns></returns>
public static async Task SetAsync(string key, object value)
{
await Instance.SetAsync(key, value);
}
}
}