这个工具类的核心作用是提供一个线程安全的 Redis 连接单例,确保应用程序中始终使用同一个 ConnectionMultiplexer 实例操作 Redis,避免频繁创建连接带来的性能损耗。所有 Redis 操作都可通过该工具类获取连接,避免重复开发连接管理逻辑。
using Infrastructure;
using StackExchange.Redis;
using System;
using System.Threading.Tasks;
namespace ZR.Infrastructure.Helper
{
/// <summary>
/// Redis 连接工具类,实现单例模式管理 ConnectionMultiplexer
/// </summary>
public static class StackExchangeRedisHelper
{
// 锁对象:保证多线程环境下创建连接的线程安全
private static readonly object _lock = new object();
// Redis 连接多路复用器(核心对象,代表与 Redis 服务器的连接)
private static ConnectionMultiplexer _mux;
/// <summary>
/// Redis 连接字符串
/// 从配置文件读取基础地址,并附加超时参数(连接超时 5 秒,同步操作超时 3 秒)
/// </summary>
private static string config = AppSettings.GetConfig("StackRedis:Redis") + ",connectTimeout=5000,syncTimeout=3000";
/// <summary>
/// 单例模式获取 ConnectionMultiplexer 实例
/// 确保全局唯一连接,避免频繁创建连接的性能开销
/// </summary>
public static ConnectionMultiplexer Mux
{
get
{
// 双重校验锁:先判断连接是否有效,无效再进入锁逻辑(减少锁竞争)
if (_mux == null || !_mux.IsConnected)
{
// 加锁:保证同一时间只有一个线程执行连接创建逻辑
lock (_lock)
{
// 再次校验:防止多线程同时通过第一层判断后,重复创建连接
if (_mux == null || !_mux.IsConnected)
{
// 保存旧连接引用,避免直接释放导致正在使用的请求报错
var oldMux = _mux;
// 创建新的连接实例(根据配置字符串连接 Redis 服务器)
_mux = ConnectionMultiplexer.Connect(config);
// 延迟释放旧连接:给正在使用旧连接的请求留时间完成操作
if (oldMux != null)
{
// 异步延迟释放(不阻塞当前线程)
Task.Run(() =>
{
try
{
// 等待 5 秒后释放旧连接(时间可根据业务调整)
Task.Delay(5000).Wait();
oldMux.Dispose();
}
catch { /* 忽略释放失败的异常,避免影响主流程 */ }
});
}
}
}
}
return _mux;
}
}
/// <summary>
/// 获取默认 Redis 数据库(0 号库)
/// </summary>
public static IDatabase Db => Mux.GetDatabase();
/// <summary>
/// 按需获取指定编号的 Redis 数据库
/// </summary>
/// <param name="db">数据库编号(默认 0 号库)</param>
/// <returns>指定数据库的操作接口</returns>
public static IDatabase GetDatabase(int db = 0) => Mux.GetDatabase(db);
}
}