news 2026/6/26 6:21:05

C#高效操作Redis全攻略

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C#高效操作Redis全攻略

一、Redis 简介

Redis 是一种开源的、基于内存的数据结构存储系统,可用作数据库、缓存和消息代理。它支持多种数据结构,包括字符串、哈希、列表、集合、有序集合等,具有极高的读写性能,在互联网开发中应用广泛。

二、环境准备

2.1 安装 Redis 服务

Windows 环境:

Redis 官方未提供 Windows 版本安装包,可使用第三方维护的版本。下载地址:https://github.com/MicrosoftArchive/redis/releases

下载后直接安装,安装完成后确保 Redis 服务设置为"自动"启动类型。

如需设置密码,找到安装目录下的redis.windows-service.conf文件,搜索# requirepass foobared,在下方添加:

requirepass 你的密码

修改后重启 Redis 服务即可。

验证安装:

打开命令行工具,进入 Redis 安装目录,输入:

redis-cli

如果设置了密码,需要先认证:

auth 你的密码

然后测试基本操作:

set testkey "Hello Redis" get testkey

能正常返回结果说明安装成功。

2.2 安装 C# 客户端库

在 C# 项目中操作 Redis,推荐使用 ‌StackExchange.Redis‌,这是 .NET 生态中最成熟、性能最好的 Redis 客户端。

通过 NuGet 安装:

Install-Package StackExchange.Redis

或使用 .NET CLI:

dotnet add package StackExchange.Redis

三、连接 Redis

3.1 单例模式连接(推荐)

ConnectionMultiplexer是线程安全的,设计为在整个应用生命周期中复用,不应频繁创建和销毁。推荐使用单例模式 + 异步初始化:

using StackExchange.Redis; public class RedisConnectionManager { private static Lazy<ConnectionMultiplexer> _lazyConnection; private static readonly object _lock = new object(); /// <summary> /// 获取 Redis 连接实例(单例) /// </summary> public static ConnectionMultiplexer Instance { get { if (_lazyConnection == null) { lock (_lock) { if (_lazyConnection == null) { _lazyConnection = new Lazy<ConnectionMultiplexer>(() => { var config = new ConfigurationOptions { EndPoints = { "127.0.0.1:6379" }, Password = "你的密码", // 无密码则省略 ConnectTimeout = 5000, // 连接超时(毫秒) SyncTimeout = 5000, // 同步操作超时(毫秒) AbortOnConnectFail = false, // 连接失败不抛异常,后台自动重试 KeepAlive = 30, // 保活间隔(秒) DefaultDatabase = 0 // 默认数据库编号 }; return ConnectionMultiplexer.Connect(config); }); } } } return _lazyConnection.Value; } } /// <summary> /// 获取数据库实例 /// </summary> public static IDatabase GetDatabase(int db = -1) { return Instance.GetDatabase(db); } /// <summary> /// 释放连接 /// </summary> public static void Dispose() { if (_lazyConnection != null && _lazyConnection.IsValueCreated) { _lazyConnection.Value.Dispose(); _lazyConnection = null; } } }

关键参数说明:

表格

参数说明
AbortOnConnectFail = false保命开关‌,首次连接失败不抛异常,后台自动重试
ConnectTimeout连接超时时间,默认 5000ms,跨网络环境可适当调大
SyncTimeout同步操作超时上限,防止线程长时间阻塞
KeepAlive心跳保活间隔,防止 NAT 设备或负载均衡器断开空闲连接

3.2 在 ASP.NET Core 中集成

// Program.cs 或 Startup.cs builder.Services.AddSingleton<ConnectionMultiplexer>(sp => { var config = new ConfigurationOptions { EndPoints = { "127.0.0.1:6379" }, Password = "你的密码", AbortOnConnectFail = false, ConnectTimeout = 5000, SyncTimeout = 5000, KeepAlive = 30 }; return ConnectionMultiplexer.Connect(config); });

使用时通过依赖注入获取:

public class MyService { private readonly ConnectionMultiplexer _redis; public MyService(ConnectionMultiplexer redis) { _redis = redis; } public async Task DoSomethingAsync() { var db = _redis.GetDatabase(); await db.StringSetAsync("key", "value"); } }

四、基本数据操作

4.1 字符串操作

字符串是 Redis 最基础的数据类型,可以存储文本、数字或序列化后的对象。

var db = RedisConnectionManager.GetDatabase(); // 设置值 db.StringSet("username", "张三"); // 设置值并指定过期时间 db.StringSet("token", "abc123", TimeSpan.FromMinutes(30)); // 获取值 RedisValue value = db.StringGet("username"); Console.WriteLine(value); // 输出: 张三 // 判断键是否存在 bool exists = db.KeyExists("username"); // 删除键 db.KeyDelete("username"); // 数值递增 db.StringSet("counter", "0"); db.StringIncrement("counter"); // 变为 1 db.StringIncrement("counter", 5); // 变为 6 // 数值递减 db.StringDecrement("counter", 2); // 变为 4 // 设置键的过期时间 db.KeyExpire("token", TimeSpan.FromHours(1)); // 查看剩余过期时间 TimeSpan? ttl = db.KeyTimeToLive("token");

重要提醒:StringGet返回的是RedisValue类型,不是普通的string。判断键是否存在应使用value.IsNull,而不是value == nullstring.IsNullOrEmpty(value)

RedisValue result = db.StringGet("不存在的键"); if (result.IsNull) { Console.WriteLine("键不存在"); }

4.2 对象序列化存储

// 定义实体类 public class User { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } } // 存储对象(JSON 序列化) var user = new User { Id = 1001, Name = "李四", Age = 25 }; string json = JsonSerializer.Serialize(user); db.StringSet("user:1001", json, TimeSpan.FromHours(2)); // 读取对象 RedisValue cachedJson = db.StringGet("user:1001"); if (!cachedJson.IsNull) { var cachedUser = JsonSerializer.Deserialize<User>(cachedJson); Console.WriteLine($"姓名: {cachedUser.Name}, 年龄: {cachedUser.Age}"); }

4.3 批量操作

避免在循环中逐个调用 Redis 命令,应使用批量操作减少网络往返:

// 批量设置 var pairs = new KeyValuePair<RedisKey, RedisValue>[] { new("key1", "value1"), new("key2", "value2"), new("key3", "value3") }; db.StringSet(pairs); // 批量获取 RedisKey[] keys = { "key1", "key2", "key3" }; RedisValue[] values = db.StringGet(keys); for (int i = 0; i < keys.Length; i++) { Console.WriteLine($"{keys[i]}: {values[i]}"); }

五、高级数据结构操作

5.1 哈希表(Hash)

适合存储对象的多个字段,如用户资料、商品信息等。

var db = RedisConnectionManager.GetDatabase(); // 设置单个字段 db.HashSet("user:1002", "name", "王五"); db.HashSet("user:1002", "age", "24"); db.HashSet("user:1002", "email", "wangwu@example.com"); // 批量设置字段 var hashEntries = new HashEntry[] { new("name", "赵六"), new("age", "30"), new("city", "北京") }; db.HashSet("user:1003", hashEntries); // 获取单个字段 RedisValue name = db.HashGet("user:1002", "name"); // 获取所有字段 HashEntry[] allFields = db.HashGetAll("user:1002"); foreach (var field in allFields) { Console.WriteLine($"{field.Name}: {field.Value}"); } // 获取指定多个字段 RedisValue[] selectedFields = db.HashGet("user:1002", new RedisValue[] { "name", "email" }); // 检查字段是否存在 bool hasField = db.HashExists("user:1002", "age"); // 删除字段 db.HashDelete("user:1002", "email"); // 数值递增(如库存管理) db.HashIncrement("product:1000", "stock", -1); // 库存减 1

5.2 列表(List)

基于链表实现,支持从两端快速插入和删除,适合消息队列、最新动态等场景。

var db = RedisConnectionManager.GetDatabase(); // 从左侧插入 db.ListLeftPush("tasks", "任务1"); db.ListLeftPush("tasks", "任务2"); db.ListLeftPush("tasks", "任务3"); // 从右侧插入 db.ListRightPush("tasks", "任务4"); // 从左侧弹出 RedisValue task = db.ListLeftPop("tasks"); // 从右侧弹出 RedisValue lastTask = db.ListRightPop("tasks"); // 获取指定范围的元素(不删除) RedisValue[] items = db.ListRange("tasks", 0, -1); // 获取全部 // 获取列表长度 long count = db.ListLength("tasks"); // 修剪列表(保留指定范围) db.ListTrim("tasks", 0, 9); // 只保留前 10 条

消息队列示例:

// 生产者 public void EnqueueOrder(string orderId) { db.ListLeftPush("order_queue", orderId); } // 消费者 public string DequeueOrder() { return db.ListRightPop("order_queue"); }

5.3 集合(Set)

无序且元素唯一的字符串集合,适合标签、去重等场景。

var db = RedisConnectionManager.GetDatabase(); // 添加元素 db.SetAdd("tags", "C#"); db.SetAdd("tags", "Redis"); db.SetAdd("tags", "数据库"); // 检查元素是否存在 bool exists = db.SetContains("tags", "C#"); // 获取所有元素 RedisValue[] allTags = db.SetMembers("tags"); // 获取集合大小 long size = db.SetLength("tags"); // 移除元素 db.SetRemove("tags", "数据库"); // 集合运算 db.SetAdd("set1", "a", "b", "c"); db.SetAdd("set2", "b", "c", "d"); RedisValue[] union = db.SetCombine(SetOperation.Union, "set1", "set2"); // 并集 RedisValue[] intersect = db.SetCombine(SetOperation.Intersect, "set1", "set2"); // 交集 RedisValue[] diff = db.SetCombine(SetOperation.Difference, "set1", "set2"); // 差集

5.4 有序集合(Sorted Set)

每个元素关联一个分数,按分数排序,适合排行榜、优先级队列等场景。

var db = RedisConnectionManager.GetDatabase(); // 添加元素(带分数) db.SortedSetAdd("leaderboard", new SortedSetEntry[] { new("玩家A", 1000), new("玩家B", 850), new("玩家C", 920), new("玩家D", 780) }); // 增加分数 db.SortedSetIncrement("leaderboard", "玩家B", 50); // 获取排名(从低到高) long? rank = db.SortedSetRank("leaderboard", "玩家A"); // 获取排名(从高到低) long? reverseRank = db.SortedSetReverseRank("leaderboard", "玩家A"); // 获取分数 double? score = db.SortedSetScore("leaderboard", "玩家A"); // 获取 Top 3 SortedSetEntry[] top3 = db.SortedSetRangeByRankWithScores( "leaderboard", 0, 2, Order.Descending); foreach (var entry in top3) { Console.WriteLine($"{entry.Element}: {entry.Score}"); }

六、发布与订阅

Redis 支持消息发布/订阅模式,适合系统间解耦通信。

// 获取订阅者 var subscriber = RedisConnectionManager.Instance.GetSubscriber(); // 订阅频道 subscriber.Subscribe("chat_channel", (channel, message) => { Console.WriteLine($"收到消息: {message}"); }); // 发布消息 subscriber.Publish("chat_channel", "Hello, Redis!"); // 取消订阅 subscriber.Unsubscribe("chat_channel");

七、事务与管道

7.1 事务

Redis 事务保证一组命令按顺序执行且不被其他命令打断。

var db = RedisConnectionManager.GetDatabase(); // 创建事务 ITransaction transaction = db.CreateTransaction(); // 添加操作 transaction.StringSetAsync("key1", "value1"); transaction.StringSetAsync("key2", "value2"); transaction.StringIncrementAsync("counter"); // 执行事务 bool committed = await transaction.ExecuteAsync();

7.2 管道(Batch)

管道将多个命令打包发送,减少网络往返,但不保证原子性。

var db = RedisConnectionManager.GetDatabase(); IBatch batch = db.CreateBatch(); // 批量添加操作 await batch.StringSetAsync("batch_key1", "value1"); await batch.StringSetAsync("batch_key2", "value2"); await batch.KeyExpireAsync("batch_key1", TimeSpan.FromMinutes(10)); // 执行 batch.Execute();

八、最佳实践

8.1 连接管理

  • 全局单例‌:ConnectionMultiplexer必须全局复用,不要在每次请求时创建新实例
  • 异步初始化‌:使用Lazy<ConnectionMultiplexer>延迟初始化,避免启动时阻塞
  • 不要缓存 IDatabase‌:IDatabase是轻量级对象,每次通过GetDatabase()获取即可

8.2 性能优化

  • 批量操作优先‌:使用StringSet(KeyValuePair[])StringGet(RedisKey[])代替循环单次调用
  • 管道减少 RTT‌:复杂混合命令使用IBatch打包
  • 合理设置过期时间‌:避免内存无限增长
  • 使用异步 API‌:所有方法都有对应的Async版本,在异步上下文中务必使用异步方法

8.3 异常处理

try { var db = RedisConnectionManager.GetDatabase(); await db.StringSetAsync("key", "value"); } catch (RedisConnectionException ex) { // 连接异常处理 Console.WriteLine($"Redis 连接失败: {ex.Message}"); } catch (RedisTimeoutException ex) { // 超时异常处理 Console.WriteLine($"Redis 操作超时: {ex.Message}"); } catch (RedisException ex) { // 其他 Redis 异常 Console.WriteLine($"Redis 异常: {ex.Message}"); }

8.4 连接字符串注意事项

  • 参数名必须‌严格小写‌,如passwordconnectTimeoutabortConnect
  • 不要使用 URL 格式(如redis://:pwd@host:6379),应使用host:port,password=xxx格式
  • Docker 或云环境必须将localhost替换为真实 IP 或服务名

九、完整示例

using StackExchange.Redis; using System.Text.Json; class Program { static async Task Main(string[] args) { // 获取数据库实例 var db = RedisConnectionManager.GetDatabase(); // 1. 缓存用户信息 var user = new { Id = 1, Name = "测试用户", Email = "test@example.com" }; string userJson = JsonSerializer.Serialize(user); await db.StringSetAsync("user:1", userJson, TimeSpan.FromMinutes(30)); // 2. 读取缓存 RedisValue cached = await db.StringGetAsync("user:1"); if (!cached.IsNull) { var cachedUser = JsonSerializer.Deserialize<object>(cached); Console.WriteLine($"缓存命中: {cachedUser}"); } // 3. 计数器 await db.StringSetAsync("page_views", "0"); await db.StringIncrementAsync("page_views"); Console.WriteLine($"页面访问量: {await db.StringGetAsync("page_views")}"); // 4. 哈希存储 await db.HashSetAsync("product:100", new HashEntry[] { new("name", "笔记本电脑"), new("price", "5999"), new("stock", "100") }); // 5. 列表操作 await db.ListLeftPushAsync("recent_orders", "ORD001"); await db.ListLeftPushAsync("recent_orders", "ORD002"); RedisValue[] orders = await db.ListRangeAsync("recent_orders", 0, -1); Console.WriteLine($"最近订单: {string.Join(", ", orders)}"); } }

通过本教程,你应该已经掌握了在 C# 中使用 StackExchange.Redis 进行连接、数据操作和性能优化的核心技能。在实际项目中,建议根据业务场景合理选择数据结构,并始终遵循单例连接、批量操作、异步调用等最佳实践。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/26 6:16:58

专业的GEO公司哪个好?选对伙伴,让品牌“智”胜未来!

随着生成式AI与搜索引擎深度融合&#xff0c;GEO&#xff08;Generative Engine Optimization&#xff0c;生成式引擎优化&#xff09; 正成为企业数字化营销的新战场。它不同于传统SEO&#xff08;只盯排名&#xff09;或SEM&#xff08;仅靠竞价&#xff09;&#xff0c;GEO的…

作者头像 李华
网站建设 2026/6/26 6:15:09

2026年将至,市面上热门的超级员工公司哪家能在AI浪潮中脱颖而出?

在当今数字化时代&#xff0c;AI技术正以前所未有的速度重塑着各个行业。据相关数据显示&#xff0c;全球AI市场规模在过去几年中呈现出爆发式增长&#xff0c;预计到2026年将达到数千亿美元。在这样的大背景下&#xff0c;超级员工公司作为AI技术在企业服务领域的重要应用&…

作者头像 李华
网站建设 2026/6/26 6:11:05

广义复合交替松弛投影算法:原理、收敛性与参数调优实战

1. 项目概述&#xff1a;从“硬算”到“巧算”的思维跃迁在数值计算和优化领域&#xff0c;我们常常会遇到一个经典难题&#xff1a;如何高效地找到一个点&#xff0c;它同时满足多个集合的约束&#xff1f;想象一下&#xff0c;你需要在城市里找一个新家&#xff0c;这个家最好…

作者头像 李华
网站建设 2026/6/26 6:10:27

超声波避障传感器赋能 AGV 侧向安全防撞与智能仓储防护

现代物流产业规模持续扩张&#xff0c;仓储转运、货物分拣等环节作业量大幅增长&#xff0c;传统人工搬运模式逐渐显现短板。人工操作不仅效率有限、数据管控易出现偏差&#xff0c;还难以快速应对货物积压、库存短缺等突发状况&#xff0c;制约了物流体系整体运转效率。在此背…

作者头像 李华
网站建设 2026/6/26 6:10:17

PCF80能看细胞内标志物吗?从细胞状态研究谈空间蛋白组应用

在肿瘤免疫微环境研究中&#xff0c;细胞功能状态往往需要结合膜蛋白、胞质蛋白和核内转录因子共同判断。例如&#xff0c;PD-1、LAG3等免疫检查点主要反映细胞膜上的免疫调控状态&#xff1b;Granzyme B、IFNγ等效应分子可用于分析细胞毒性和炎症反应&#xff1b;TOX、FOXP3等…

作者头像 李华