跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

Redis Set 数据类型 C++ 实战指南

Redis Set 是一种无序且元素唯一的字符串集合数据结构。基于 C++ redis-plus-plus 库演示了 Set 的核心操作与高级应用。内容涵盖基础命令如添加成员、获取数量及成员检查,重点解析交集、并集、差集等集合运算在服务器端的高效执行。通过实际代码示例展示了 SISMEMBER、SCARD、SPOP 等命令的用法及时间复杂度优势,帮助开发者利用 Redis 实现去重、权限控制、社交关系分析及任务队列等功能,提升系统性能与开发效率。

灵魂伴侣发布于 2026/1/17更新于 2026/9/1164 浏览
Redis Set 数据类型 C++ 实战指南

Redis Set 基础与 C++ 实战

Redis Set 是一种无序且元素唯一的字符串集合数据结构。本文基于 C++ redis-plus-plus 库演示了 Set 的核心操作与高级应用。

Redis Set 概念

想象一个魔力袋,你可以往里面扔东西,但有两条特殊规则:

  1. 强制保持唯一:自动拒绝重复的物品。
  2. 顺序毫不在意:取出的顺序是随机的。

这个'魔力袋'正是 Redis Set 的精准比喻:一个无序的、元素唯一的字符串集合。这使得它能够以惊人的速度进行成员资格检查、数量统计以及复杂的服务器端运算。

第一章:基础入门 - 创建和查看你的第一个 Set

使用 SADD 和 SMEMBERS 命令。

SADD:向集合中添加成员

SADD 用于添加一个或多个元素。如果元素已存在,Redis 会忽略它。返回值是新成功添加的元素数量。

SMEMBERS:获取所有成员

返回指定 Set 中的所有成员。注意:在拥有数百万元素的超大 Set 上使用此命令可能会暂时阻塞您的 Redis 服务器。后续章节将讨论更安全的替代方案 SSCAN。

C++ 实战:sadd 与 smembers
#include <iostream>
#include <set>
#include <string>
#include <vector>
#include <iterator>
#include <sw/redis++/redis.h>

// 辅助函数,用于打印容器内容
template<typename T>
void PrintContainer(const T& container) {
    for (const auto& elem : container) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;
}

void  {
    std::cout <<  << std::endl;
    
    redis.();
    
    
    redis.(, );
    
    
    redis.(, {, , });
    
    
    std::set<std::string> elems = {, , };
    
    redis.(, elems.(), elems.());
    
    
    std::set<std::string> result;
    
     it = std::(result, result.());
    
    redis.(, it);
    (result);
}
test1
(sw::redis::Redis& redis)
"sadd 和 smembers"
// 清空数据库,确保一个干净的测试环境
flushall
// 1. 一次添加一个元素
sadd
"key"
"111"
// 2. 使用初始化列表,一次添加多个元素
sadd
"key"
"222"
"333"
"444"
// 3. 使用迭代器,从另一个容器中添加多个元素
"555"
"666"
"777"
// 返回值是成功插入了多少个元素
sadd
"key"
begin
end
// --- 现在,让我们获取所有元素 ---
// 为我们的 C++ set 构建一个插入迭代器
auto
inserter
end
// 从 Redis set 中获取所有成员,并插入到我们的 C++ set 中
smembers
"key"
PrintContainer
代码剖析
  1. redis.flushall():清空整个 Redis 数据库,确保测试环境纯净。
  2. 单个元素 sadd:redis.sadd("key", "111"); 将字符串 '111' 添加到名为 key 的 Set 中。由于 Set 原本是空的,此命令返回 1。
  3. 初始化列表 sadd:redis.sadd("key", {"222", "333", "444"}); 展示了 redis-plus-plus 库的一个便捷特性,允许您一次性添加多个元素。这比发送三个独立的命令效率更高。此调用将返回 3。
  4. 基于迭代器的 sadd:先填充了一个 C++ 的 std::set,然后使用它的迭代器(elems.begin(), elems.end())将其所有元素添加到 Redis 的 Set 中。这对于将现有 C++ 容器中的数据同步到 Redis 非常有用。
  5. 使用 smembers 获取数据:
    • 我们创建了一个 std::set<string> result; 来存放从 Redis 返回的数据。在客户端使用 std::set 是一个绝佳选择,因为它不仅镜像了 Redis Set 的唯一性,还能自动对元素进行排序,便于展示。
    • auto it = std::inserter(result, result.end()); 是关键。我们需要一种方式告诉 redis-plus-plus 应该把接收到的元素放在哪里。inserter 是一种特殊的迭代器,当你给它赋值时,它会调用其关联容器的 insert() 方法。
    • redis.smembers("key", it); 执行命令。redis-plus-plus 获取 key 中的所有成员,并使用我们的迭代器 it 将它们逐一插入到 result 集合中。
C++ 关键概念:inserter vs back_inserter
  • std::back_inserter 创建一个调用 push_back() 的迭代器。适用于 std::vector, std::list, std::deque 等容器。
  • std::set没有push_back() 方法,因为它需要维护内部的排序。因此,对于 std::set,我们必须使用 std::inserter,它会调用 insert() 方法。
预测输出

PrintContainer 函数将打印 result 集合的内容。由于 std::set 会对其元素进行排序,输出将是按字母/数字顺序排列的。

sadd 和 smembers 111 222 333 444 555 666 777 

第二章:深入探索 - 检查与修改你的 Set

SISMEMBER:这个元素存在吗? (时间复杂度 O(1))

SISMEMBER 检查一个特定元素是否是 Set 的成员。如果存在,返回 1 (true);如果不存在,返回 0 (false)。性能是 O(1),不依赖于 Set 的大小。

C++ 实战:sismember
void test2(sw::redis::Redis& redis) {
    std::cout << "sismember" << std::endl;
    redis.flushall();
    redis.sadd("key", {"111", "222", "333", "444"});
    
    // 检查 "111" 是否是集合的成员
    bool result = redis.sismember("key", "111");
    std::cout << "result:" << result << std::endl;
}
  • 剖析:redis-plus-plus 库非常方便地将 Redis 返回的 1 或 0 直接映射为了 C++ 的 bool 类型。因为 '111' 确实在 Set 中,result 将为 true。
  • 应用场景:标签系统、权限控制、唯一性事件检查。
  • 预测输出:sismember result:1
SCARD:集合里有多少元素? (时间复杂度 O(1))

SCARD 代表 'Set Cardinality'(集合基数),返回一个 Set 中元素的数量。这也是一个 O(1) 操作。

C++ 实战:scard
void test3(sw::redis::Redis& redis) {
    std::cout << "scard" << std::endl;
    redis.flushall();
    // 向集合中添加 4 个唯一元素
    redis.sadd("key", {"111", "222", "333", "444"});
    
    // 获取集合中的元素个数
    long long result = redis.scard("key");
    // 返回 4
    std::cout << "result:" << result << std::endl;
}
  • 应用场景:在线用户跟踪、点赞计数、独立 IP 统计。
  • 预测输出:scard result:4
SPOP:随机移除并返回一个元素

SPOP 会从 Set 中随机选择一个元素,将其移除,然后返回给你。这是一种'破坏性读取'。

C++ 实战:spop
void test4(sw::redis::Redis& redis) {
    std::cout << "spop" << std::endl;
    redis.flushall();
    redis.sadd("key", {"111", "222", "333", "444"});
    
    // 随机弹出一个元素,spop 的返回值是 Optional<string>
    auto result = redis.spop("key");
    if (result) {
        // 因为返回值是 Optional,我们通过 .value() 来获取原始的 string 内容
        std::cout << "result:" << result.value() << std::endl;
    } else {
        std::cout << "result is empty" << std::endl;
    }
}
  • 剖析:redis-plus-plus 将返回值包装在 sw::redis::Optional<std::string> 中。这是因为如果你对一个空 Set 执行 spop,Redis 会返回 nil(空)。Optional 类型可以优雅地处理这种情况。
  • 核心特性:随机性:非常适合抽奖系统、任务队列分配、在线匹配。
  • 预测输出:输出不确定,可能是 111, 222, 333 或 444 之一。

第三章:集合的威力 - 集合运算

Redis 能够在服务器端以极高的效率执行集合的交集 (intersection)、并集 (union) 和差集 (difference) 运算。

交集运算:SINTER & SINTERSTORE
  • SINTER: 计算交集并直接返回给客户端。
  • SINTERSTORE: 计算交集,但不返回,而是将结果存储在一个新的目标 Set 中。
C++ 实战:sinter (求交集并返回)
void test5(sw::redis::Redis& redis) {
    std::cout << "sinter" << std::endl;
    redis.flushall();
    redis.sadd("key1", {"111", "222", "333", "444"});
    redis.sadd("key2", {"111", "222", "444"});
    
    std::set<std::string> result;
    auto it = std::inserter(result, result.end());
    
    // 求交集涉及多个 key,我们使用初始化列表来描述
    // 将 "key1" 和 "key2" 的交集插入到 result 中
    redis.sinter({"key1", "key2"}, it);
    PrintContainer(result);
}
  • 预测输出:sinter 111 222 444
C++ 实战:sinterstore (求交集并存储)
void test6(sw::redis::Redis& redis) {
    std::cout << "sinterstore" << std::endl;
    redis.flushall();
    redis.sadd("key1", {"111", "222", "333"});
    redis.sadd("key2", {"111", "222", "444"});
    
    // 指定一个 destination ("key3"),将交集结果存储到其中
    long long len = redis.sinterstore("key3", {"key1", "key2"});
    std::cout << "len:" << len << std::endl;
    
    // 检查 "key3" 中的元素以验证结果
    std::set<std::string> result;
    auto it = std::inserter(result, result.end());
    redis.smembers("key3", it);
    PrintContainer(result);
}
  • 预测输出:sinterstore len:2 111 222

第四章:超越基础 - 更多强大的 Set 命令

并集运算:SUNION & SUNIONSTORE

返回所有给定集合的全部不重复的元素。适用于好友圈合并、权限合并等场景。

差集运算:SDIFF & SDIFFSTORE

返回那些只存在于第一个集合中,但不在任何后续集合中的元素。适用于好友推荐、内容去重等场景。

安全迭代:SSCAN

SMEMBERS 对于大集合是危险的。SSCAN 提供了安全的替代方案。它使用一个游标 (cursor) 来分批次地返回集合中的元素,每次只返回一小部分,绝不会阻塞服务器。

总结

Redis Set 是一种看似简单却异常强大的数据结构。核心优势包括:

  • 唯一性:自动处理数据去重,简化了应用逻辑。
  • 极速性能:绝大多数核心操作(增、删、查、计数)的时间复杂度都是 O(1),性能与集合大小无关。
  • 强大的集合运算:能够在服务器端原子性地、高效地执行交、并、差集运算,极大地减少了网络开销和客户端的计算压力。

从简单的在线用户统计,到复杂的社交网络好友关系分析,再到智能推荐系统,Redis Set 都能以其优雅和高效提供坚实的解决方案。

目录

  1. Redis Set 基础与 C++ 实战
  2. Redis Set 概念
  3. 第一章:基础入门 - 创建和查看你的第一个 Set
  4. SADD:向集合中添加成员
  5. SMEMBERS:获取所有成员
  6. C++ 实战:sadd 与 smembers
  7. 代码剖析
  8. C++ 关键概念:inserter vs back_inserter
  9. 预测输出
  10. 第二章:深入探索 - 检查与修改你的 Set
  11. SISMEMBER:这个元素存在吗? (时间复杂度 O(1))
  12. C++ 实战:sismember
  13. SCARD:集合里有多少元素? (时间复杂度 O(1))
  14. C++ 实战:scard
  15. SPOP:随机移除并返回一个元素
  16. C++ 实战:spop
  17. 第三章:集合的威力 - 集合运算
  18. 交集运算:SINTER & SINTERSTORE
  19. C++ 实战:sinter (求交集并返回)
  20. C++ 实战:sinterstore (求交集并存储)
  21. 第四章:超越基础 - 更多强大的 Set 命令
  22. 并集运算:SUNION & SUNIONSTORE
  23. 差集运算:SDIFF & SDIFFSTORE
  24. 安全迭代:SSCAN
  25. 总结

更多推荐文章

查看全部
  • Qt 键盘输入法开源方案
  • 基于 YOLOv8-v12 与 SpringBoot 的轴承缺陷检测系统
  • Python 异步爬虫结合 K8S 弹性伸缩构建高并发采集系统
  • VSCode 搭建 Python 运行与调试环境
  • C++ Qt 网络编程:QUdpSocket、QTcpSocket 与 Http 实战
  • Effective Modern C++:理解特殊成员函数的生成机制
  • Python 爬虫零基础入门:系统路线与工程化实战
  • 最大子数组和算法解析:暴力、动态规划与贪心(Java)
  • 前端应用监控方案与最佳实践
  • Python 高阶函数 map() 原理与实战应用
  • Java 核心面试题与解析:基础、并发、容器篇
  • 大模型幻觉问题深度治理:技术体系、工程实践与未来演进
  • flux-kontext-pro 深度解析:前端状态管理从入门到精通
  • C++ 继承进阶:多继承、菱形继承与虚继承机制
  • C++ 泛型编程:代码复用的核心利器
  • Python Django Web 框架实战:构建产品管理系统
  • Ubuntu 安装 VSCode 三种方法及常见问题解决
  • Coze扣子「百套AI工作流」模板合集
  • 基于 Python 和 AI 的智能害虫识别助手搭建
  • 开源医疗大模型 Llama3-Aloe-8B-Alpha 技术特性与性能分析

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online