一、当集合遇见Redis

Redis作为高性能内存数据库,其Set(集合)数据类型凭借天然去重、高效交集运算等特性,在标签系统、共同好友等场景大放异彩。而StackExchange.Redis作为.NET生态最成熟的Redis客户端,其优雅的API设计让操作集合如虎添翼。今天我们就通过真实代码示例,手把手教你玩转这套组合拳!

二、环境搭建速成指南

1. 必要装备清单

# NuGet安装命令(技术栈:StackExchange.Redis 2.6.90)
Install-Package StackExchange.Redis

2. 连接初始化

using StackExchange.Redis;
using System.Text.Json;

// 创建单例连接(生产环境建议使用连接池)
var conn = ConnectionMultiplexer.Connect("localhost:6379");
IDatabase redisDb = conn.GetDatabase();

三、集合操作

1. 基础招式:增删改查

// 添加元素到集合(支持批量操作)
redisDb.SetAdd("user:1001:tags", new RedisValue[] { "C#", "Redis", "Dotnet" });

// 删除指定元素
bool isDeleted = redisDb.SetRemove("user:1001:tags", "Java"); 

// 获取所有成员(注意:结果无序!)
RedisValue[] allTags = redisDb.SetMembers("user:1001:tags");
Console.WriteLine($"用户标签:{string.Join(",", allTags)}");

// 判断元素是否存在
bool exists = redisDb.SetContains("user:1001:tags", "Redis");

2. 高阶心法:集合运算

// 计算并集(多个集合合并)
RedisKey[] groupKeys = { "group:A:members", "group:B:members" };
redisDb.SetCombineAndStore(SetOperation.Union, "total_members", groupKeys);

// 获取交集(共同好友场景)
RedisValue[] commonFriends = redisDb.SetCombine(
    SetOperation.Intersect, 
    new RedisKey[] { "user:1001:friends", "user:1002:friends" }
);

// 差集运算(A有B无的元素)
var uniqueElements = redisDb.SetCombine(
    SetOperation.Difference,
    new RedisKey[] { "product:2023:views", "product:2024:views" }
);

3. 实用技巧:随机与计数

// 获取随机元素(抽奖场景)
RedisValue luckyMember = redisDb.SetRandomMember("activity:lucky_draw");

// 获取集合基数(元素总数)
long totalCount = redisDb.SetLength("daily_active_users");

// 弹出随机元素(破坏性读取)
RedisValue poppedItem = redisDb.SetPop("pending_tasks");

四、典型业务场景剖析

场景1:电商商品标签系统

// 给商品打标签
redisDb.SetAdd("product:888:tags", "手机");
redisDb.SetAdd("product:888:tags", "5G");

// 通过标签筛选商品
var phoneProducts = redisDb.SetMembers("tag:手机:products");

场景2:社交共同好友

// 存储用户好友关系
redisDb.SetAdd("user:1001:friends", new[] { 2001, 2003, 2005 });
redisDb.SetAdd("user:1002:friends", new[] { 2003, 2005, 2007 });

// 获取共同好友(高性能计算)
var common = redisDb.SetCombine(SetOperation.Intersect, 
    new RedisKey[] { "user:1001:friends", "user:1002:friends" });

五、技术选型双刃剑

优势亮点:

  1. 毫秒级集合运算(10万级数据求交集仅需3ms)
  2. 自动去重节省存储空间
  3. 原子操作保证数据一致性
  4. 原生支持分布式集群

潜在短板:

  1. 无序存储不适合需要顺序的场景
  2. 超大集合(百万级)性能下降明显
  3. 不支持二级索引查询

六、避坑指南与最佳实践

  1. 元素序列化陷阱
// 错误示范:直接存储对象
var user = new User{Id=1001};
redisDb.SetAdd("users", user); // 导致存储类型错误!

// 正确做法:序列化为字符串
redisDb.SetAdd("users", JsonSerializer.Serialize(user));
  1. 连接管理三不要
  • 不要频繁创建/销毁连接
  • 不要忘记配置AbortOnConnectFail
  • 不要在多线程中共享ConnectionMultiplexer实例
  1. 性能优化技巧
  • 批量操作使用RedisValue[]代替循环
  • 定期清理过期集合
  • 对超大集合采用分片策略(例:user:1001:tags:shard1)

七、总结与展望

通过本文的实战演练,我们掌握了使用StackExchange.Redis操作Redis集合的核心技巧。这种组合在需要快速去重、关系运算的场景表现卓越,但在面对复杂查询时仍需配合其他数据结构。随着RedisJSON等模块的普及,集合类型与其他数据结构的配合使用将成为新的探索方向。