news 2026/6/24 19:42:24

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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 等)。

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

数仓系列:数仓开发工程师学习路线图

引言要找到一份数仓开发工作&#xff0c;核心在于掌握 SQL能力、大数据技术栈以及数仓理论模型、真实项目经验。 阶段 1&#xff1a;基础能力 理解数据仓库理论 掌握 Linux/SQL 基础阶段 2&#xff1a;核心技能 掌握 Hadoop 生态 Hive Spark 开发关键能力&#xff1a; 能独…

作者头像 李华
网站建设 2026/6/24 3:16:01

一键生成瑜伽女孩图片:雯雯的后宫-造相Z-Image-瑜伽女孩使用教程

一键生成瑜伽女孩图片&#xff1a;雯雯的后宫-造相Z-Image-瑜伽女孩使用教程 想快速生成一张充满活力、姿态优美的瑜伽女孩图片吗&#xff1f;无论是为你的社交媒体寻找配图&#xff0c;还是为瑜伽课程设计宣传海报&#xff0c;手动绘制或寻找合适的图片往往费时费力。今天&am…

作者头像 李华
网站建设 2026/6/18 3:54:07

AI头像生成器快速入门:无需代码的AI绘图神器

AI头像生成器快速入门&#xff1a;无需代码的AI绘图神器 你是不是也遇到过这样的烦恼&#xff1f;想给自己换个酷炫的头像&#xff0c;但自己不会画画&#xff0c;找设计师又太贵&#xff0c;网上找的模板又千篇一律&#xff0c;毫无个性。 别担心&#xff0c;今天我要给你介…

作者头像 李华
网站建设 2026/6/13 23:31:19

清音刻墨在教育场景落地:网课视频自动打轴字幕生成案例

清音刻墨在教育场景落地&#xff1a;网课视频自动打轴字幕生成案例 1. 引言&#xff1a;教育视频的字幕痛点与解决方案 在线教育已经成为现代学习的重要方式&#xff0c;但很多老师和机构在制作网课视频时都面临一个共同难题&#xff1a;如何快速准确地为视频添加字幕。传统的…

作者头像 李华
网站建设 2026/6/22 9:38:16

小白友好:星图平台部署Qwen3-VL:30B图文教程

小白友好&#xff1a;星图平台部署Qwen3-VL:30B图文教程 1. 你能学会什么&#xff1f;零基础也能上手的多模态办公助手搭建指南 你是不是也遇到过这些场景&#xff1a; 想快速分析一张产品截图里的参数表格&#xff0c;却要手动抄写再整理&#xff1f;飞书群里同事发来十几张…

作者头像 李华