当前位置: 首页 > news >正文

Redis 解锁:C++ 实战深度探索 Set 数据类型

你的标题是“Redis 解锁:C++ 实战深度探索 Set 数据类型”,看起来像是想深入探讨 Redis 的Set数据类型在 C++ 中的实战用法,同时可能把“解锁”理解为“解锁分布式锁”的意思(因为 Redis 分布式锁和 SET 命令关系非常密切),或者单纯想全面掌握 Set 类型。

下面我把两个方向都给你讲清楚,并重点用redis-plus-plus(目前最流行的 C++ Redis 客户端)来写实战代码。

1. Redis Set 数据类型核心特性与典型用法

Redis 的 Set 是无序、不重复的字符串集合,底层实现有两种:

  • intset(小集合 + 全是整数时)
  • hashtable(ziplist 编码已废弃,新版用 dict)

常用命令(时间复杂度几乎都是 O(1) 或 O(N) 很小):

命令作用时间复杂度示例
SADD添加一个或多个元素O(1)SADD myset “apple” “banana”
SREM删除元素O(1)SREM myset “apple”
SISMEMBER判断元素是否存在O(1)SISMEMBER myset “apple”
SCARD获取集合元素个数O(1)SCARD myset
SMEMBERS获取所有元素O(N)SMEMBERS myset
SRANDMEMBER随机返回一个/多个元素O(1) / O(N)SRANDMEMBER myset 3
SPOP随机弹出并删除元素O(1)SPOP myset
SUNION并集O(N)SUNION set1 set2
SINTER交集O(N)SINTER set1 set2
SDIFF差集O(N)SDIFF set1 set2

典型业务场景

  • 抽奖系统(随机抽取用户)
  • 标签系统(用户打标签,去重)
  • 共同好友、共同关注
  • 访问用户去重(UV 统计)
  • 黑名单 / 白名单
  • 秒杀商品库存校验(但更常用 string 或 lua)

2. C++ 中使用 redis-plus-plus 操作 Set(推荐方式)

先安装 redis-plus-plus(基于 hiredis,线程安全,支持连接池)

# 假设你用 vcpkg 或自己编译vcpkginstallredis-plus-plus

基本连接与 Set 操作示例

#include<sw/redis++/redis++.h>#include<iostream>#include<vector>#include<string>usingnamespacesw::redis;intmain(){try{// 单节点连接(推荐使用连接池)ConnectionOptions opts;opts.host="127.0.0.1";opts.port=6379;// opts.password = "yourpass"; // 如有密码// 连接池(生产推荐)ConnectionPoolOptions pool_opts;pool_opts.size=16;// 连接数pool_opts.wait_timeout=std::chrono::milliseconds(100);pool_opts.connection_timeout=std::chrono::seconds(5);autoredis=Redis(RedisURI("tcp://127.0.0.1:6379"),pool_opts);// --------------------- Set 操作 ---------------------std::string key="myset:fruits";// 清空测试数据(慎用生产环境)redis.del(key);// SADD 添加元素(支持批量)longlongcnt=redis.sadd(key,{"apple","banana","orange","apple"});// apple 只加一次std::cout<<"Added "<<cnt<<" unique elements\n";// 输出 3// SISMEMBER 判断存在if(redis.sismember(key,"banana")){std::cout<<"banana exists\n";}// SCARD 元素个数std::cout<<"Size: "<<*redis.scard(key)<<"\n";// 3// SMEMBERS 获取全部(小心大集合)std::vector<std::string>members;redis.smembers(key,std::back_inserter(members));std::cout<<"All members: ";for(constauto&m:members)std::cout<<m<<" ";std::cout<<"\n";// SRANDMEMBER 随机取(不删除)autorand_one=redis.srandmember(key);if(rand_one)std::cout<<"Random: "<<*rand_one<<"\n";// SPOP 随机弹出并删除autopopped=redis.spop(key);if(popped)std::cout<<"Popped: "<<*popped<<"\n";// SREM 删除redis.srem(key,"orange");// 集合运算示例redis.sadd("set:a",{"1","2","3","4"});redis.sadd("set:b",{"3","4","5","6"});std::vector<std::string>inter;redis.sinter({"set:a","set:b"},std::back_inserter(inter));std::cout<<"Intersection: ";for(auto&v:inter)std::cout<<v<<" ";// 3 4std::cout<<"\n";}catch(constError&e){std::cerr<<"Redis error: "<<e.what()<<std::endl;return1;}return0;}

3. Redis 分布式锁才是“解锁”最经典的场景(SET + NX + PX)

Redis 官方推荐的单节点分布式锁就是用SET命令(不是 Set 类型,而是 String 类型):

SET lock:order:12345 "uuid-xxx-clientA" NX PX 30000
  • NX:不存在才设置(加锁)
  • PX:毫秒级过期(防死锁)
  • value 必须唯一(通常是 UUID + 客户端标识)

C++ 实现简单版分布式锁(非 Redlock)

#include<sw/redis++/redis++.h>#include<string>#include<random>#include<chrono>#include<thread>classSimpleRedisLock{private:Redis&_redis;std::string _lock_key;std::string _lock_value;std::chrono::milliseconds _expire_ms;public:SimpleRedisLock(Redis&r,conststd::string&key,intexpire_seconds=30):_redis(r),_lock_key(key),_expire_ms(std::chrono::seconds(expire_seconds)){}booltry_lock(){// 生成唯一 value(简单示例,可用 uuid 库)std::random_device rd;std::mt19937gen(rd());std::uniform_int_distribution<>dis(10000000,99999999);_lock_value="client-"+std::to_string(dis(gen));autoreply=_redis.set(_lock_key,_lock_value,std::chrono::duration_cast<std::chrono::milliseconds>(_expire_ms),UpdateType::ONLY_IF_NOT_EXIST);// 等价 NXreturnreply&&*reply;// true 表示加锁成功}boolunlock(){// 安全解锁:用 Lua 脚本保证原子性staticconstchar*lua_script=R"( if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end )";autores=_redis.eval<longlong>(lua_script,{_lock_key},{_lock_value});returnres&&*res==1;}~SimpleRedisLock(){unlock();// 析构自动尝试释放(视业务可去掉)}};// 使用示例voidprocess_order(Redis&redis){SimpleRedisLocklock(redis,"lock:order:12345",30);if(!lock.try_lock()){std::cout<<"获取锁失败\n";return;}std::cout<<"获得锁,开始处理订单...\n";std::this_thread::sleep_for(std::chrono::seconds(5));// 模拟业务lock.unlock();std::cout<<"订单处理完成,已释放锁\n";}

更安全的做法

  • 用 redis-plus-plus 自带的Redlock(多节点)
  • 或引入Redisson的思想,用更完善的续期机制(watchdog)
// redis-plus-plus 内置 Redlock 用法(需多个 master 节点)autoredlock=Redlock({node1,node2,node3,node4,node5});if(redlock.lock("my-resource",std::chrono::seconds(30))){// 业务redlock.unlock();}

总结对比

需求推荐数据类型核心命令C++ 库支持度
去重、标签、抽奖SetSADD / SPOP / SRANDMEMBER非常好
分布式锁(单节点)StringSET NX PX优秀
高可用分布式锁StringRedlock 算法redis++ 支持
排行榜Sorted SetZADD / ZRANGE-

如果你真正想问的是Set 类型的深度实战,还是分布式锁的 C++ 实现,可以再补充具体场景,我可以继续给你更细致的代码或优化方案(Lua 续期、Redlock 完整实现、 fencing token 等)。

http://www.jsqmd.com/news/365361/

相关文章:

  • 【Django毕设源码分享】基于Django的环保公益项目众筹平台的设计与实现(程序+文档+代码讲解+一条龙定制)
  • 大迈出海:中国制造全球化下外贸流程询盘无忧的深度赋能伙伴 - 品牌策略主理人
  • ELISPOT酶联免疫斑点技术综述
  • Delphi GIF动画显示教程与第三方组件推荐
  • 2026年口碑好的新能源铝合金管材公司推荐,细聊国强和茂产品怎么样 - mypinpai
  • 【C++】多态到底难在哪?虚函数表 + 动态绑定,一篇吃透底层逻辑
  • 【Django毕设源码分享】基于Django+Python的购物管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)
  • 石英玻璃退火点测试仪供应商综合实力排行榜:口碑、服务、售后一网打尽 - 品牌推荐大师
  • Z-Image-Turbo实测:6B小模型竟有如此惊人的绘画细节
  • 《C++进阶之STL》【哈希表】
  • 【Django毕设源码分享】基于Django+Vue的双相情感障碍交流平台(程序+文档+代码讲解+一条龙定制)
  • Qwen3-ASR-0.6B语音识别进阶:音频质量评分模块集成与低质音频预警
  • 分析华埔建筑装饰工程有限公司,郑州地区性价比高的装修品牌推荐 - 工业设备
  • GLM-4.7-Flash参数详解:temperature/top_p/max_tokens调优指南
  • 小白友好:星图平台部署Qwen3-VL:30B图文教程
  • 告别单调配音!VibeVoice+cpolar:多角色语音生成随时随地搞创作
  • 一键生成瑜伽女孩图片:雯雯的后宫-造相Z-Image-瑜伽女孩使用教程
  • 03 Python的集合类型
  • 【Django毕设源码分享】基于Django的网络设备租赁系统的设计与实现(程序+文档+代码讲解+一条龙定制)
  • 腾讯混元模型部署避坑:vllm启动常见问题解决方案
  • Qwen1.5-1.8B-Chat-GPTQ-Int4效果实测:中文情感分析、观点抽取、舆情摘要生成
  • 手把手教你使用OFA模型:图片与英文语义关系一键分析
  • MusePublic生成质量展示:30步推理下细节还原度与画质稳定性
  • 【Django毕设源码分享】基于Django+Python的膳食健康系统的设计与实现(程序+文档+代码讲解+一条龙定制)
  • 学霸同款AI论文软件,千笔ai写作 VS 灵感风暴AI,专科生专属利器!
  • C++——多态
  • DeepSeek-OCR-2小白入门:3步完成文档结构化提取
  • Qwen3-TTS声音设计功能实测:打造个性化语音方案
  • mPLUG-Owl3-2B本地化教程:国产昇腾910B芯片适配可行性验证与精度对比
  • AudioLDM-S开源大模型价值再定义:环境音效生成领域的垂直开源标杆