如何在C++中使用Redis的事务功能?

一、Redis 事务核心原理(C++ 视角)

Redis 事务通过MULTI(开启事务)→ 执行多个命令(入队)→EXEC(提交事务)/DISCARD(取消事务)完成,hiredis 库中需按此流程依次发送命令,且所有入队命令仅在 EXEC 后执行

  • WATCH:可选,监控指定 key,若事务执行前 key 被修改,事务会被取消(乐观锁);
  • MULTI:标记事务开始,后续命令进入队列而非立即执行;
  • EXEC:执行队列中的所有命令,返回所有命令结果;
  • DISCARD:清空队列,取消事务。

二、C++ 实现 Redis 事务的完整代码

以下示例包含基础事务、带 WATCH 的事务、取消事务三种场景,基于 hiredis 库实现:

cpp

运行

#include <iostream> #include <string> #include <hiredis/hiredis.h> using namespace std; // 连接Redis(复用之前的连接函数) redisContext* connectRedis(const string& ip, int port, const string& password = "") { struct timeval timeout = {10, 0}; redisContext* ctx = redisConnectWithTimeout(ip.c_str(), port, timeout); if (ctx == nullptr || ctx->err) { if (ctx) { cerr << "连接失败:" << ctx->errstr << endl; redisFree(ctx); } else { cerr << "连接对象创建失败!" << endl; } return nullptr; } // 密码认证 if (!password.empty()) { redisReply* reply = (redisReply*)redisCommand(ctx, "AUTH %s", password.c_str()); if (reply == nullptr || reply->type == REDIS_REPLY_ERROR) { cerr << "认证失败:" << (reply ? reply->str : "无返回") << endl; freeReplyObject(reply); redisFree(ctx); return nullptr; } freeReplyObject(reply); } return ctx; } // 执行单个Redis命令(辅助函数) redisReply* execCmd(redisContext* ctx, const char* cmd, ...) { if (!ctx) return nullptr; va_list args; va_start(args, cmd); redisReply* reply = (redisReply*)redisvCommand(ctx, cmd, args); va_end(args); if (reply && reply->type == REDIS_REPLY_ERROR) { cerr << "命令错误:" << reply->str << endl; } return reply; } int main() { // 1. 连接Redis(替换为你的配置) redisContext* ctx = connectRedis("127.0.0.1", 6379, ""); if (!ctx) return -1; // ==================== 场景1:基础事务(MULTI + EXEC) ==================== cout << "===== 基础事务 =====" << endl; // 1.1 开启事务 redisReply* reply = execCmd(ctx, "MULTI"); if (reply && reply->str == string("OK")) { cout << "事务已开启" << endl; } freeReplyObject(reply); // 1.2 入队命令(仅入队,不执行) reply = execCmd(ctx, "SET user:1:name Alice"); // 命令1 freeReplyObject(reply); reply = execCmd(ctx, "HSET user:1 age 25 gender female"); // 命令2 freeReplyObject(reply); reply = execCmd(ctx, "GET user:1:name"); // 命令3 freeReplyObject(reply); // 1.3 提交事务(执行所有入队命令) reply = execCmd(ctx, "EXEC"); if (reply && reply->type == REDIS_REPLY_ARRAY) { cout << "事务执行结果:" << endl; // 遍历EXEC返回的数组(对应入队命令的结果) for (size_t i = 0; i < reply->elements; i++) { redisReply* elem = reply->element[i]; if (elem->type == REDIS_REPLY_STATUS) { cout << " 命令" << i+1 << ":" << elem->str << endl; } else if (elem->type == REDIS_REPLY_STRING) { cout << " 命令" << i+1 << ":" << elem->str << endl; } else if (elem->type == REDIS_REPLY_INTEGER) { cout << " 命令" << i+1 << ":" << elem->integer << endl; } } } freeReplyObject(reply); // ==================== 场景2:带WATCH的事务(乐观锁) ==================== cout << "\n===== 带WATCH的事务 =====" << endl; // 2.1 先设置一个初始值 reply = execCmd(ctx, "SET balance 100"); freeReplyObject(reply); // 2.2 监控balance键(乐观锁:若该键被修改,事务取消) reply = execCmd(ctx, "WATCH balance"); freeReplyObject(reply); // 2.3 开启事务,入队扣减余额命令 reply = execCmd(ctx, "MULTI"); freeReplyObject(reply); reply = execCmd(ctx, "DECRBY balance 50"); // 扣减50 freeReplyObject(reply); // 【模拟其他客户端修改balance(触发WATCH)】 // 注释掉这行,事务会成功;放开注释,事务会返回空(执行失败) // reply = execCmd(ctx, "SET balance 200"); // 外部修改WATCH的key // freeReplyObject(reply); // 2.4 提交事务 reply = execCmd(ctx, "EXEC"); if (reply == nullptr) { cout << "事务执行失败(连接异常)" << endl; } else if (reply->type == REDIS_REPLY_NIL) { // WATCH的key被修改,事务取消,EXEC返回nil cout << "事务取消(WATCH的key被修改)" << endl; } else if (reply->type == REDIS_REPLY_ARRAY) { cout << "事务成功,扣减后余额:" << reply->element[0]->integer << endl; } freeReplyObject(reply); // ==================== 场景3:取消事务(DISCARD) ==================== cout << "\n===== 取消事务 =====" << endl; reply = execCmd(ctx, "MULTI"); freeReplyObject(reply); reply = execCmd(ctx, "SET temp key123"); // 入队一个命令 freeReplyObject(reply); // 取消事务(清空队列) reply = execCmd(ctx, "DISCARD"); if (reply && reply->str == string("OK")) { cout << "事务已取消" << endl; } freeReplyObject(reply); // 验证temp键是否存在(应为不存在) reply = execCmd(ctx, "GET temp"); if (reply->type == REDIS_REPLY_NIL) { cout << "temp键未被设置(事务取消生效)" << endl; } freeReplyObject(reply); // 断开连接 redisFree(ctx); return 0; }

三、核心代码解释

  1. 事务流程关键步骤

    • WATCH balance:监控balance键,若事务执行前该键被其他客户端修改,EXEC会返回nil,事务取消;
    • MULTI:开启事务后,后续SET/HSET/DECRBY等命令仅入队,不会立即执行;
    • EXEC:提交事务,Redis 批量执行队列中的所有命令,返回一个数组(每个元素对应入队命令的结果);
    • DISCARD:清空命令队列,取消当前事务,不会执行任何入队命令。
  2. EXEC 返回值处理

    • 事务成功:返回REDIS_REPLY_ARRAY类型,数组长度等于入队命令数,每个元素对应命令的执行结果;
    • 事务取消(WATCH 触发):返回REDIS_REPLY_NIL
    • 命令错误:入队时语法错误会直接返回错误,但不影响其他命令入队;运行时错误(如对字符串执行 HSET)仅该命令失败,其他命令仍执行(Redis 事务不支持回滚)。

四、Redis 事务的注意事项(C++ 开发重点)

  1. 无回滚机制:Redis 事务中某条命令执行失败(如类型错误),其他命令仍会执行,需在代码中自行校验命令合法性;
  2. WATCH 仅一次有效EXEC/DISCARD后,WATCH会自动取消,若需再次监控需重新执行WATCH
  3. 资源释放:每个redisReply都需调用freeReplyObject释放,避免内存泄漏;
  4. 连接异常处理:事务执行中若连接断开,队列中的命令不会执行,需在代码中增加重连和重试逻辑;
  5. 进阶替代方案:若需强事务支持(如回滚),可使用 Redis 6.0 + 的CLUSTER事务或 Lua 脚本(EVAL),Lua 脚本会原子性执行所有命令,且支持条件判断。

总结

  1. C++ 中使用 Redis 事务的核心流程是:WATCH(可选) → MULTI → 入队命令 → EXEC/DISCARD
  2. EXEC的返回值是数组类型,需遍历解析每个命令的结果,WATCH触发时返回nil
  3. Redis 事务无回滚机制,需注意命令合法性校验,且WATCH仅提供乐观锁能力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1163732.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

医疗数据用Apache Beam实时流处理稳预警

&#x1f4dd; 博客主页&#xff1a;jaxzheng的CSDN主页 实时医疗预警&#xff1a;Apache Beam驱动的流处理架构与稳健性革命目录实时医疗预警&#xff1a;Apache Beam驱动的流处理架构与稳健性革命 引言&#xff1a;医疗数据实时化浪潮中的关键瓶颈 一、技术应用场景&#xff…

C++ 中解锁 Redis

一、核心前提&#xff1a;选择 Redis C 客户端库C 本身没有内置 Redis 客户端&#xff0c;主流选择是hiredis&#xff08;官方推荐的 C 语言客户端&#xff0c;轻量、稳定&#xff0c;C 可直接调用&#xff09;&#xff0c;也是最基础、最常用的库。1. 环境安装&#xff08;以 …

互联网大厂Java求职面试实录:Spring Boot、微服务与AI技术全解析

互联网大厂Java求职面试实录&#xff1a;Spring Boot、微服务与AI技术全解析 本文通过互联网大厂Java求职者谢飞机与严肃面试官的三轮面试对话&#xff0c;涵盖Java核心技术栈、微服务、数据库、消息队列及AI应用场景&#xff0c;结合电商及智能客服业务&#xff0c;逐步深入&a…

网络安全入门教程(非常详细)从零基础入门到精通,看完这一篇你就是网络安全高手了。

关于我 我算是“入行”不久的一个新人安全工作者&#xff0c;为什么是引号呢&#xff0c;因为我是个“半个野路子”出身。早在13年的时候&#xff0c;我在初中时期就已经在90sec、wooyun等社区一直学习、报告漏洞。后来由于升学的压力&#xff0c;我逐渐淡出了安全圈子&#x…

Windows Server SMB 共享文件 回收站

1. 项目简介 ShareRecycleBin 是一个专为 Windows Server (特别是 SMB 共享环境) 设计的增量回收站服务。它通过硬链接 (Hard Link) 技术实现对文件的“即时备份”&#xff0c;并能在文件被删除时将其移动到指定的回收站目录&#xff0c;同时保留原始的目录结构和权限锁定。 …

从0到1:零基础入门黑客网络安全,这一篇就够了!(非常详细)

前言 零基础要怎么学黑客技术&#xff1f;作为八年网安人&#xff0c;分享我一套最强的学习攻略&#xff0c;就算你是新手小白&#xff0c;也可以知道从哪里开始入门&#xff01; 一、入门基础 作为没有学过计算机的新手小白&#xff0c;首先要做的就是把基础打牢&#xff0…

C语言中switch case使用技巧,告别冗长if-else代码

在C语言中&#xff0c;switch case语句是一种高效的多分支选择结构&#xff0c;相比连续的if-else语句&#xff0c;它在处理多个确定值的情况时更加清晰和简洁。合理使用switch case不仅能提高代码可读性&#xff0c;还能在某些情况下优化程序性能。本文将深入探讨switch case的…

网络安全入门到精通:2026转行必备指南,收藏这篇就够了!

网络安全入门到精通&#xff1a;2026转行必备指南&#xff0c;收藏这篇就够了&#xff01; 本文详细介绍了2026年网络安全行业的薪资情况、工作内容与前景&#xff0c;提供了从入门到专家的职业发展路径。文章涵盖网络安全基础知识、权威认证获取、实践经验积累及领域专注选择…

leetcode 870. Advantage Shuffle 优势洗牌

Problem: 870. Advantage Shuffle 优势洗牌 解题过程 贪心&#xff0c;nums2排序&#xff0c;带上索引的&#xff0c;对nu从小到大遍历的&#xff0c;排序nums1&#xff0c;对每个nu的数字i&#xff0c;从nums1中找到比它大的最小数字&#xff0c;因nu排序了&#xff0c;nums1也…

如何一步步将 ASP.NET MVC 升级为.NET

引言 将 ASP.NET MVC 应用从.NET Framework 升级到现代.NET 并不是简单的版本提升。此次迁移代表了运行时、托管模型、配置系统、依赖注入和 HTTP 流水线架构的转变。许多团队低估了这一点&#xff0c;把它当作标准的框架升级&#xff0c;结果在流程后期才发现他们应用中的核心…

文心5.0登上LMArena文本榜国内第一,1月22日或将正式发布

1月15日&#xff0c;LMArena 大模型竞技场最新排名显示&#xff0c;文心大模型ERNIE-5.0-0110以1460分登上LMArena文本榜国内第一、全球第八&#xff0c;超过GPT-5.1-High、Gemini-2.5-Pro等多款国内外主流模型。其中&#xff0c;在数学能力排名中&#xff0c;ERNIE-5.0-0110 位…

基于Flexbox的现代化CSS框架:Bulma快速入门指南

Bulma Bulma 是一个基于 Flexbox 的现代化 CSS 框架&#xff0c;专注于提供优雅的 UI 组件和响应式布局解决方案。 功能特性 纯 CSS 框架&#xff1a;项目输出仅为单个 CSS 文件&#xff08;bulma.css&#xff09;&#xff0c;不包含任何 JavaScript&#xff0c;可以与任何 …

lemon评测系统在哪下载安全?官方渠道与使用指南

对于想要获取lemon评测系统的用户来说&#xff0c;了解如何安全下载和正确使用这款工具是首要任务。作为一款性能测试软件&#xff0c;它能帮助开发者评估应用程序在不同环境下的运行表现&#xff0c;但在下载和使用过程中需要注意几个关键点。 lemon评测系统是什么软件 lemon评…

【精华收藏】模型微调技术详解:从原理到实践的全面指南,解锁大模型在医疗、金融等领域的垂直应用

模型微调是连接通用AI模型与垂直领域需求的关键技术&#xff0c;通过针对性参数优化使大模型从"博学"变为"专精"。文章详细介绍了微调原理、应用场景、分类方法&#xff08;全参数微调与参数高效微调&#xff09;、实施流程及实际案例&#xff0c;帮助开发…

【好写作AI】跨学科“鸡尾酒”调制师:专治论文“理论乱炖”与“术语打架”

好写作AI官方网址&#xff1a;https://www.haoxiezuo.cn/一、做跨学科研究的你&#xff0c;是否每天都在“学术巴别塔”里当翻译&#xff1f;术语互殴&#xff1a;A学科的“能动性”和B学科的“主体性”是一个意思吗&#xff1f;查了半天文献&#xff0c;更晕了。理论脱臼&…

绿城郑州爱心公益网站毕业论文+PPT(附源代码+演示视频)

文章目录绿城郑州爱心公益网站一、项目简介&#xff08;源代码在文末&#xff09;1.运行视频2.&#x1f680; 项目技术栈3.✅ 环境要求说明4.包含的文件列表&#xff08;含论文&#xff09;数据库结构与测试用例系统功能结构前端运行截图后端运行截图项目部署源码下载绿城郑州爱…

深度测评专科生必备!2026 TOP10 AI论文网站评测与推荐

深度测评专科生必备&#xff01;2026 TOP10 AI论文网站评测与推荐 为什么需要一份专属专科生的AI论文网站榜单&#xff1f; 随着人工智能技术在教育领域的深入应用&#xff0c;越来越多的专科生开始借助AI工具提升论文写作效率。然而&#xff0c;面对市场上五花八门的平台&…

【好写作AI】AI来了,学术伦理就崩了?我们用行动说不!

好写作AI官方网址&#xff1a;https://www.haoxiezuo.cn/一、深夜的良心拷问&#xff1a;用了AI的论文&#xff0c;还算“我”的吗&#xff1f; 当你好不容易用好写作AI搞定摘要、理清逻辑、降重到8%后&#xff0c;准备点击提交的瞬间&#xff0c;那个幽灵般的问题总会出现&…

导师推荐10个AI论文平台,助你搞定本科生毕业论文!

导师推荐10个AI论文平台&#xff0c;助你搞定本科生毕业论文&#xff01; AI 工具如何助力论文写作&#xff1f; 在当前的学术环境中&#xff0c;越来越多的学生开始借助 AI 工具来提升论文写作的效率和质量。尤其是在面对毕业论文这一重要任务时&#xff0c;合理利用 AI 技术不…

导师严选9个AI论文工具,继续教育学生轻松搞定论文写作!

导师严选9个AI论文工具&#xff0c;继续教育学生轻松搞定论文写作&#xff01; AI 工具助力论文写作&#xff0c;高效又省心 在当今学术研究日益数字化的背景下&#xff0c;AI 工具正逐渐成为学生和科研工作者不可或缺的得力助手。尤其对于继续教育领域的学习者来说&#xff0c…