惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Simon Willison's Weblog
Simon Willison's Weblog
Google DeepMind News
Google DeepMind News
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
P
Proofpoint News Feed
Recent Announcements
Recent Announcements
MongoDB | Blog
MongoDB | Blog
U
Unit 42
云风的 BLOG
云风的 BLOG
Recorded Future
Recorded Future
G
Google Developers Blog
I
InfoQ
Blog — PlanetScale
Blog — PlanetScale
A
About on SuperTechFans
Jina AI
Jina AI
量子位
宝玉的分享
宝玉的分享
The Cloudflare Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - 聂微东
Last Week in AI
Last Week in AI
WordPress大学
WordPress大学
美团技术团队
The Hacker News
The Hacker News
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
Tailwind CSS Blog
博客园 - 司徒正美
博客园 - 叶小钗
Hugging Face - Blog
Hugging Face - Blog
P
Palo Alto Networks Blog
博客园_首页
阮一峰的网络日志
阮一峰的网络日志
博客园 - 【当耐特】
Spread Privacy
Spread Privacy
The GitHub Blog
The GitHub Blog
Y
Y Combinator Blog
Vercel News
Vercel News
Martin Fowler
Martin Fowler
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Forbes - Security
Forbes - Security
Attack and Defense Labs
Attack and Defense Labs
Google DeepMind News
Google DeepMind News
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Microsoft Azure Blog
Microsoft Azure Blog
P
Privacy International News Feed
G
GRAHAM CLULEY
The Last Watchdog
The Last Watchdog
C
Cyber Attacks, Cyber Crime and Cyber Security
AI
AI
V2EX - 技术
V2EX - 技术

博客园 - VipSoft

MinerU - 将非结构化文档(PDF、图片、Office 文件等)转换为机器可读的 Markdown 和 JSON LangChain 入门 服务端部署-FastAPI LangChain 入门 LangSmith LangChain 入门 实战 - 食谱推荐 LangChain 入门 Memory 会话记忆 LangChain 入门 Tools 工具 LangChain 入门 Tools 工具 LangChain 入门 Prompts 提示词 LangChain 入门 Message 消息 LangChain 入门 Model 的初始化和调用 LangChain 入门 Agent 的基本运行机制 AI 0基础学习,名词解析 LangChain 和 LangGraph AI大模型知识体系 Dify — Workflow - 数据可视化 Dify — 连接MySQL配置 Dify — Chatflow - 数据库智能查询 Dify — Chatflow - 文档知识库 Dify — Agent 智能体 高安全券码、注册码生成 Dify — 文本生成应用 Dify — 聊天助手 -- 知识库 Windows 下 Docker 安装 Dify Ollama — 命令 Ollama — 为什么能够运行不同的模型 Ollama — 接口 Qwen — 自定义模型文件 Ollama Qwen — 安装测试 Ollama Windows 安装 & 指定安装目录 跟着AI学AI - 诊断结论信息抽取 - 批量处理脚本 跟着AI学AI - 诊断结论信息抽取 - 模型压缩与部署 跟着AI学AI - 诊断结论信息抽取 - 模型评估与调试 跟着AI学AI - 诊断结论信息抽取 - 模型训练 轻型民用无人驾驶航空器安全操控理论考试培训材料 Windbg w3wp.DMP 内存分析 跟着AI学AI - 诊断结论信息抽取 - 数据增强 QQ 录屏软件 Java - 加权随机算法 - 示例 Java - 加权随机算法--Demo Java LoadBalanceUtil 负载均衡、轮询加权 SpringBoot 集成 IP2Region 获取IP地域信息 Windows 服务器和虚拟主机,创建.开头的文件夹 .well-known 跟着AI学AI - 诊断结论信息抽取 - 数据格式转换BERT训练格式 跟着AI学AI - 诊断结论信息抽取 - LabelStudio 标注 -- 结论标注 跟着AI学AI - 诊断结论信息抽取 - 学习路径 跟着AI学AI - UV 安装 数据标注工具 Label-Studio `VIRTUAL_ENV=venv` does not match the project environment 跟着AI学AI - 学习路径 - 命名实体识别(NER)和信息抽取(IE) 跟着AI学AI - 需要购买显卡吗? C# 无BOM的UTF-8编码 Vue ref reactive Vue - el-table 嵌套表 Spring `@Scheduled` 中这些参数的区别、组合和应用场景 Python 找出同步日志中的重复数据 Python - UV PyCharm 不能识别 .venv 的环境
FreeRedis Helper
VipSoft · 2026-04-29 · via 博客园 - VipSoft

对于 FreeRedis 的版本选择,最直接的答案是:使用最新稳定版 1.5.5

下面是选择它的理由和详细的版本分析,方便你做出判断。

📊 版本选择建议

版本系列 推荐程度 说明
v1.5.x ⭐⭐⭐⭐⭐ 强烈推荐 当前最新主线版本,功能最全、性能最好、Bug修复最及时,适合绝大多数新项目。
v1.4.x ⭐⭐⭐ 不推荐新项目 这是较旧的稳定分支,仅当你的项目有特殊的兼容性要求时(如对AOT编译有特定限制)才考虑。
v1.3.x 及更早 不推荐 版本较老,缺乏很多新特性和性能优化,不建议在新项目中使用。

🔍 详细分析

1. 为什么要选最新稳定版?

  • 最新版本 1.5.5 发布于 2025-12-10,功能最完善,性能最佳。
  • 修复所有已知Bug:较新的版本会包含对之前问题的修复。
  • 全面支持 Redis 新特性:FreeRedis 从设计之初就紧跟 Redis 的发展,v1.5.x 系列对 RESP3 协议、客户端缓存等特性有非常好的支持。
  • 活跃维护:项目更新频繁,选择最新版意味着你的技术债务最少。

2. 有什么潜在风险吗?

使用最新稳定版的风险极低。FreeRedis 的作者是 .NET 开源社区非常有经验的开发者(也是 CSRedisCore 和 FreeSql 的作者),项目质量和代码规范有保障。同时,它有庞大的单元测试(超过268个)作为质量保证,并且从 NuGet 上看,已有超过145万次下载,被大量项目验证过。

📦 如何安装

在你的项目中,通过 NuGet 包管理器控制台执行以下命令即可:

PM> Install-Package FreeRedis -Version 1.5.5

或者,如果你在 .csproj 项目文件中手动管理包引用,可以添加以下条目:

<PackageReference Include="FreeRedis" Version="1.5.5" />

💡 总结

  • 对于新项目直接使用 1.5.5
  • 对于现有项目:如果使用的是 1.4.x1.3.x,可以放心升级到 1.5.5。FreeRedis 版本间的 API 变化非常小,升级几乎是无痛的。

FreeRedis 本身已经内置了连接池,默认配置下:
max poolsize = 100(最大连接数)
min poolsize = 5(最小连接数)

FreeRedisConfig.cs

namespace VipSoft.FreeRedis
{
    /// <summary>
    /// FreeRedis 配置类
    /// </summary>
    public class FreeRedisConfig
    {
        /// <summary>
        /// Redis 连接字符串,格式:127.0.0.1:6379,password=123,defaultDatabase=0
        /// </summary>
        public string ConnectionString { get; set; } = "127.0.0.1:6379";

        /// <summary>
        /// 连接池最大数量,默认 100
        /// </summary>
        public int MaxPoolSize { get; set; } = 100;

        /// <summary>
        /// 连接池最小数量,默认 5
        /// </summary>
        public int MinPoolSize { get; set; } = 5;

        /// <summary>
        /// 连接超时时间(毫秒),默认 10000
        /// </summary>
        public int ConnectTimeout { get; set; } = 10000;

        /// <summary>
        /// 空闲连接超时时间(毫秒),默认 20000
        /// </summary>
        public int IdleTimeout { get; set; } = 20000;

        /// <summary>
        /// Key 前缀(可选),所有操作的 key 会自动添加此前缀
        /// </summary>
        public string KeyPrefix { get; set; } = string.Empty;

        /// <summary>
        /// 是否启用 SSL,默认 false
        /// </summary>
        public bool Ssl { get; set; } = false;

        /// <summary>
        /// Redis 密码
        /// </summary>
        public string Password { get; set; } = string.Empty;

        /// <summary>
        /// 默认数据库索引,默认 0
        /// </summary>
        public int DefaultDatabase { get; set; } = 0;
    }
}

RedisHelper.cs

using System;
using System.Collections.Generic;
using FreeRedis;
using NLog;
using System.Collections.Concurrent;
using System.Configuration;
using System.Linq;
using Newtonsoft.Json;

namespace VuoSift.FreeRedis
{
    /// <summary>
    /// RedisHelper 单例类(支持多数据库实例)
    /// </summary>
    public class RedisHelper : IDisposable
    {
        // 存储不同数据库索引的实例
        private static readonly ConcurrentDictionary<int, RedisHelper> _instances = new ConcurrentDictionary<int, RedisHelper>();

        private RedisClient _redisClient;
        private FreeRedisConfig _config;
        private bool _disposed = false;
        private readonly object _lockObj = new object();
        private readonly int _databaseIndex;

        // 日志
        private static readonly Logger logger = LogManager.GetCurrentClassLogger();

        /// <summary>
        /// 私有构造函数,支持指定数据库索引
        /// </summary>
        private RedisHelper(int databaseIndex = 0)
        {
            _databaseIndex = databaseIndex;
            var config = new FreeRedisConfig
            {
                ConnectionString = ConfigurationManager.AppSettings["RedisHost"] ?? "127.0.0.1:6379",
                Password = ConfigurationManager.AppSettings["RedisPassword"] ?? "",
                DefaultDatabase = databaseIndex, // 使用传入的数据库索引作为默认数据库
            };

            Initialize(config);
        }

        /// <summary>
        /// 获取指定数据库的 RedisHelper 实例
        /// </summary>
        /// <param name="databaseIndex">数据库索引(0-15)</param>
        /// <returns>RedisHelper 实例</returns>
        public static RedisHelper GetInstance(int databaseIndex = 0)
        {
            return _instances.GetOrAdd(databaseIndex, idx => new RedisHelper(idx));
        }

        /// <summary>
        /// 初始化 Redis 连接
        /// </summary>
        public void Initialize(FreeRedisConfig config = null)
        {
            if (_redisClient != null)
            {
                logger.Warn($"RedisHelper (DB:{_databaseIndex}) 已经初始化过,跳过重复初始化");
                return;
            }

            lock (_lockObj)
            {
                if (_redisClient != null) return;

                _config = config ?? new FreeRedisConfig();
                // 确保使用实例的数据库索引
                if (_config.DefaultDatabase != _databaseIndex)
                {
                    _config.DefaultDatabase = _databaseIndex;
                }

                try
                {
                    var connectionString = BuildConnectionString();
                    _redisClient = new RedisClient(connectionString);

                    // 配置序列化(重要!) -- 为了兼容老数据,这边放方法里去使用
                    //_redisClient.Serialize = obj =>
                    //{
                    //    if (obj == null) return null;
                    //    // 使用 System.Text.Json
                    //    return System.Text.Json.JsonSerializer.Serialize(obj);
                    //};

                    //_redisClient.Deserialize = (json, type) =>
                    //{
                    //    if (string.IsNullOrEmpty(json)) return null;
                    //    // 使用 System.Text.Json
                    //    return System.Text.Json.JsonSerializer.Deserialize(json, type);
                    //};

                    // 或者使用 Newtonsoft.Json
                    // _redisClient.Serialize = obj => Newtonsoft.Json.JsonConvert.SerializeObject(obj);
                    // _redisClient.Deserialize = (json, type) => Newtonsoft.Json.JsonConvert.DeserializeObject(json, type);

                    // 测试连接
                    var pingResult = _redisClient.Ping();
                    if (pingResult == "PONG")
                    {
                        logger.Info($"Redis 连接成功,数据库: {_databaseIndex}");
                    }
                    else
                    {
                        logger.Error($"Redis Ping 失败,数据库: {_databaseIndex}");
                    }
                }
                catch (Exception ex)
                {
                    logger.Error(ex, $"Redis 初始化失败,数据库: {_databaseIndex}");
                    throw;
                }
            }
        }

        private string BuildConnectionString()
        {
            var parts = new List<string>();

            // 基础地址
            parts.Add(_config.ConnectionString.Split(',')[0]);

            // 密码
            if (!string.IsNullOrEmpty(_config.Password))
                parts.Add($"password={_config.Password}");

            // 默认数据库
            if (_config.DefaultDatabase != 0)
                parts.Add($"defaultDatabase={_config.DefaultDatabase}");

            // 连接池配置
            if (_config.MaxPoolSize != 100)
                parts.Add($"max poolsize={_config.MaxPoolSize}");
            if (_config.MinPoolSize != 5)
                parts.Add($"min poolsize={_config.MinPoolSize}");

            // 超时配置
            if (_config.ConnectTimeout != 10000)
                parts.Add($"connectTimeout={_config.ConnectTimeout}");
            if (_config.IdleTimeout != 20000)
                parts.Add($"idleTimeout={_config.IdleTimeout}");

            // SSL
            if (_config.Ssl)
                parts.Add($"ssl=true");

            // Key 前缀
            if (!string.IsNullOrEmpty(_config.KeyPrefix))
                parts.Add($"prefix={_config.KeyPrefix}");

            return string.Join(",", parts);
        }

        /// <summary>
        /// 获取当前实例使用的数据库索引
        /// </summary>
        public int DatabaseIndex => _databaseIndex;

        /// <summary>
        /// 获取原始 RedisClient(推荐直接使用)
        /// </summary>
        public RedisClient GetClient()
        {
            if (_redisClient == null)
                throw new InvalidOperationException($"RedisHelper (DB:{_databaseIndex}) 未初始化,请先调用 Initialize 方法");
            return _redisClient;
        }

        /// <summary>
        /// 获取指定数据库的客户端(临时切换数据库)
        /// </summary>
        public RedisClient GetDatabase(int dbIndex)
        {
            return GetClient().GetDatabase(dbIndex);
        }

        /// <summary>
        /// 执行操作(自动管理数据库切换)
        /// </summary>
        public T Execute<T>(int dbIndex, Func<RedisClient, T> action)
        {
            using (var db = GetDatabase(dbIndex))
            {
                return action(db);
            }
        }

        /// <summary>
        /// 执行操作(无返回值)
        /// </summary>
        public void Execute(int dbIndex, Action<RedisClient> action)
        {
            using (var db = GetDatabase(dbIndex))
            {
                action(db);
            }
        }


        /// <summary>
        /// 序列化对象
        /// </summary>
        private string SerializeValue<T>(T value)
        {
            if (value == null)
                return null;

            // 如果是字符串或基础类型,直接转换为字符串
            if (typeof(T) == typeof(string))
                return value as string;

            if (typeof(T).IsPrimitive || typeof(T) == typeof(decimal))
                return Convert.ToString(value);

            // 复杂类型使用 JSON 序列化
            return JsonConvert.SerializeObject(value);
        }

        /// <summary>
        /// 反序列化对象
        /// </summary>
        private T DeserializeValue<T>(string value)
        {
            if (string.IsNullOrEmpty(value))
                return default(T);

            // 如果是字符串类型,直接返回
            if (typeof(T) == typeof(string))
                return (T)(object)value;

            // 如果是基础类型,尝试转换
            if (typeof(T).IsPrimitive || typeof(T) == typeof(decimal))
            {
                try
                {
                    return (T)Convert.ChangeType(value, typeof(T));
                }
                catch
                {
                    return default(T);
                }
            }

            // 复杂类型使用 JSON 反序列化
            return JsonConvert.DeserializeObject<T>(value);
        }

        #region 基础操作(默认使用实例的数据库)

        /// <summary>
        /// 设置键值对
        /// </summary>
        public void Set<T>(string key, T value, int? expireSeconds = null)
        {
            var serializedFields = SerializeValue(value);
            if (expireSeconds.HasValue)
                GetClient().Set(key, serializedFields, expireSeconds.Value);
            else
                GetClient().Set(key, serializedFields);
        }

        /// <summary>
        /// 设置键值对 -- 兼容老代码
        /// </summary>
        public void SetBySeconds<T>(string key, T value, int? expireSeconds = null)
        {
            var serializedFields = SerializeValue(value);
            if (expireSeconds.HasValue)
                GetClient().Set(key, serializedFields, expireSeconds.Value);
            else
                GetClient().Set(key, serializedFields);
        }

        /// <summary>
        /// 设置键值对(带过期时间)
        /// </summary>
        public bool SetNx<T>(string key, T value, int expireSeconds)
        {
            return GetClient().SetNx(key, value, expireSeconds);
        }

        /// <summary>
        /// 获取键对应的值
        /// </summary>
        public T Get<T>(string key)
        {
            var value =  GetClient().Get<string>(key);
            if (value == null)
            {
                return default(T);
            }
            return DeserializeValue<T>(value);
        }

        /// <summary>
        /// 获取键对应的值,如果不存在返回默认值
        /// </summary>
        public T Get<T>(string key, T defaultValue)
        {
            var value = GetClient().Get<T>(key);
            if (value == null)
                return defaultValue;
            return value;
        }

        /// <summary>
        /// 删除指定键
        /// </summary>
        public long Del(params string[] keys)
        {
            return GetClient().Del(keys);
        }

        /// <summary>
        /// 设置过期时间(秒)
        /// </summary>
        public bool Expire(string key, int seconds)
        {
            return GetClient().Expire(key, seconds);
        }

        /// <summary>
        /// 获取键的剩余过期时间(秒)
        /// </summary>
        public long Ttl(string key)
        {
            return GetClient().Ttl(key);
        }

        /// <summary>
        /// 递增
        /// </summary>
        public long Incr(string key)
        {
            return GetClient().Incr(key);
        }

        /// <summary>
        /// 递增指定步长
        /// </summary>
        public long IncrBy(string key, long increment)
        {
            return GetClient().IncrBy(key, increment);
        }

        /// <summary>
        /// 递减
        /// </summary>
        public long Decr(string key)
        {
            return GetClient().Decr(key);
        }

        /// <summary>
        /// 递减指定步长
        /// </summary>
        public long DecrBy(string key, long decrement)
        {
            return GetClient().DecrBy(key, decrement);
        }

        #endregion

        #region 哈希表操作(支持对象序列化)


        /// <summary>
        /// 哈希表:看 hash key 存不存在
        /// </summary>
        public long HDel(string key, string field)
        {
            var result = 0L;
            try
            {
                result = GetClient().HDel(key, field);
            }
            catch (Exception ex)
            {
                logger.Error(ex, ex.Message);
            }
            return result;
        }

        /// <summary>
        /// 哈希表:看 hash key 存不存在
        /// </summary>
        public bool HExists(string key, string field)
        {
            var result = false;
            try
            {
                result = GetClient().HExists(key, field);
            }
            catch (Exception ex)
            {
                logger.Error(ex, ex.Message);
            }
            return result;
        }

        /// <summary>
        /// 哈希表:设置字段值(自动处理对象序列化)
        /// </summary>
        public bool HSet<T>(string key, string field, T value)
        {
            var result = false;
            try
            {
                var serializedValue = SerializeValue(value);
                result = GetClient().HSet(key, field, serializedValue) > 0;
            }
            catch (Exception ex)
            {
                logger.Error(ex, ex.Message);
            }
            return result;
        }
        /// <summary>
        /// 哈希表:获取字段值(自动处理对象反序列化)
        /// </summary>
        public T HGet<T>(string key, string field)
        {
            var value = GetClient().HGet<string>(key, field);
            if (value == null)
                return default(T);

            return DeserializeValue<T>(value);
        }


        public long HMSet<T>(string key, Dictionary<string, T> fields)
        {
            var result = 0L;
            try
            {
                var serializedFields = new Dictionary<string, string>();
                foreach (var kvp in fields)
                {
                    serializedFields[kvp.Key] = SerializeValue(kvp.Value);
                }
                // 尝试使用 HMSet
                GetClient().HMSet(key, serializedFields);
                result = serializedFields.Count;
            }
            catch (Exception ex)
            {
                logger.Error(ex, ex.Message);
            }
            return result;
        }


        /// <summary>
        /// 哈希表:获取所有字段和值(自动处理对象反序列化)
        /// </summary>
        public Dictionary<string, T> HGetAll<T>(string key)
        {
            try
            {
                var dict = GetClient().HGetAll<string>(key);
                if (dict == null || dict.Count == 0)
                    return new Dictionary<string, T>();

                var result = new Dictionary<string, T>();
                foreach (var kvp in dict)
                {
                    result[kvp.Key] = DeserializeValue<T>(kvp.Value);
                }
                return result;
            }
            catch (Exception ex)
            {
                logger.Error(ex, ex.Message);
            }
            return null;
        }

        public List<T> HGetValues<T>(string key)
        {
            try
            {
                var dictionary = HGetAll<T>(key);
                if (dictionary == null || dictionary.Count == 0)
                {
                    return new List<T>();
                }
                return dictionary.Values.ToList();
            }
            catch (Exception ex)
            {
                logger.Error(ex, ex.Message);
            }
            return null;
        }

        #endregion

        #region 列表操作

        /// <summary>
        /// 列表:左侧推入
        /// </summary>
        public long LPush<T>(string key, params T[] values)
        {
            return GetClient().LPush(key, values);
        }

        /// <summary>
        /// 列表:右侧推入
        /// </summary>
        public long RPush<T>(string key, params T[] values)
        {
            return GetClient().RPush(key, values);
        }

        public List<T> LPop<T>(string key)
        {
            try
            {
                var value = GetClient().LPop<string>(key);
                if (value == null)
                    return default(List<T>);
                return DeserializeValue<List<T>>(value);
            }
            catch (Exception ex)
            {
                logger.Error(ex, ex.Message);
            }
            return null;
        }


        /// <summary>
        /// 列表:右侧弹出
        /// </summary>
        public List<T> RPop<T>(string key)
        {
            try
            {
                var value = GetClient().RPop<string>(key);
                if (value == null)
                    return default(List<T>);
                return DeserializeValue<List<T>>(value);
            }
            catch (Exception ex)
            {
                logger.Error(ex, ex.Message);
            }
            return null;
        }

        /// <summary>
        /// 列表:获取指定范围的元素
        /// </summary>
        public T[] LRange<T>(string key, long start, long stop)
        {
            return GetClient().LRange<T>(key, start, stop);
        }

        /// <summary>
        /// 列表:获取列表长度
        /// </summary>
        public long LLen(string key)
        {
            return GetClient().LLen(key);
        }

        #endregion

        #region 集合操作

        /// <summary>
        /// 集合:添加成员
        /// </summary>
        public long SAdd<T>(string key, params T[] members)
        {
            return GetClient().SAdd(key, members);
        }

        /// <summary>
        /// 集合:获取所有成员
        /// </summary>
        public T[] SMembers<T>(string key)
        {
            return GetClient().SMembers<T>(key);
        }

        /// <summary>
        /// 集合:判断是否包含成员
        /// </summary>
        public bool SIsMember<T>(string key, T member)
        {
            return GetClient().SIsMember(key, member);
        }

        /// <summary>
        /// 集合:删除成员
        /// </summary>
        public long SRem<T>(string key, params T[] members)
        {
            return GetClient().SRem(key, members);
        }

        /// <summary>
        /// 集合:获取集合大小
        /// </summary>
        public long SCard(string key)
        {
            return GetClient().SCard(key);
        }

        #endregion

        #region 有序集合操作

        /// <summary>
        /// 有序集合:添加带分数的成员
        /// </summary>
        public bool ZAdd(string key, decimal score, string member)
        {
            return GetClient().ZAdd(key, score, member) > 0;
        }

        /// <summary>
        /// 有序集合:添加带分数的成员(double 重载)
        /// </summary>
        public bool ZAdd(string key, double score, string member)
        {
            return GetClient().ZAdd(key, (decimal)score, member) > 0;
        }

        /// <summary>
        /// 有序集合:按分数范围获取成员
        /// </summary>
        public string[] ZRangeByScore(string key, decimal min, decimal max, int? limit = null, int offset = 0)
        {
            if (limit.HasValue)
                return GetClient().ZRangeByScore(key, min, max, limit.Value, offset);
            return GetClient().ZRangeByScore(key, min, max);
        }

        /// <summary>
        /// 有序集合:按分数范围获取成员(double 重载)
        /// </summary>
        public string[] ZRangeByScore(string key, double min, double max, int? limit = null, int offset = 0)
        {
            return ZRangeByScore(key, (decimal)min, (decimal)max, limit, offset);
        }

        /// <summary>
        /// 有序集合:获取成员分数
        /// </summary>
        public decimal? ZScore(string key, string member)
        {
            return GetClient().ZScore(key, member);
        }

        /// <summary>
        /// 有序集合:删除成员
        /// </summary>
        public long ZRem(string key, params string[] members)
        {
            return GetClient().ZRem(key, members);
        }

        /// <summary>
        /// 有序集合:获取有序集合的大小
        /// </summary>
        public long ZCard(string key)
        {
            return GetClient().ZCard(key);
        }

        /// <summary>
        /// 有序集合:增加成员的分数
        /// </summary>
        public decimal ZIncrBy(string key, decimal increment, string member)
        {
            return GetClient().ZIncrBy(key, increment, member);
        }

        /// <summary>
        /// 有序集合:按排名范围获取成员
        /// </summary>
        public string[] ZRange(string key, long start, long stop)
        {
            return GetClient().ZRange(key, start, stop);
        }

        /// <summary>
        /// 有序集合:获取成员的排名(从0开始)
        /// </summary>
        public long? ZRank(string key, string member)
        {
            return GetClient().ZRank(key, member);
        }

        /// <summary>
        /// 有序集合:获取成员的倒序排名(从0开始)
        /// </summary>
        public long ZRevRank(string key, string member)
        {
            return GetClient().ZRevRank(key, member);
        }

        #endregion

        #region Lua 脚本

        /// <summary>
        /// 执行 Lua 脚本
        /// </summary>
        public object Eval(string script, params string[] keys)
        {
            return GetClient().Eval(script, keys);
        }

        /// <summary>
        /// 执行 Lua 脚本(带 KEYS 参数)
        /// </summary>
        public object Eval(string script, string[] keys, params object[] args)
        {
            return GetClient().Eval(script, keys, args);
        }

        #endregion

        public void Dispose()
        {
            if (_disposed) return;
            lock (_lockObj)
            {
                if (_disposed) return;
                _redisClient?.Dispose();
                _redisClient = null;
                _disposed = true;
            }
        }
    }
}