云计算百科
云计算领域专业知识百科平台

Redis事务学习笔记

文章目录

  • 前言
  • 一、先搞懂:Redis事务到底是什么?
  • 二、四大核心命令 课堂实操案例
    • 1. MULTI + EXEC 正常提交事务
    • 2. DISCARD 放弃事务,清空队列
    • 3. WATCH 乐观锁,解决并发数据冲突
  • 三、致命大坑:Redis事务**不支持自动回滚**
    • 场景1:组队阶段语法错误 → 整个事务全部作废
    • 场景2:组队无错误,执行时报错 → 正确命令正常生效,不会回滚
    • 官方不做回滚的设计原因(面试标准答案)
  • 四、Redis事务 VS MySQL事务 ACID对比
    • Redis事务独有两个特性
  • 五、Redis事务适用&不适用场景
    • 适合使用
    • 不推荐使用
  • 六、期末/面试高频简答题汇总
  • 结尾小结

前言

Redis事务不同于MySQL事务,接下来,请跟随我的脚步,一起来学习吧


提示:以下是本篇文章正文内容,下面案例可供参考

一、先搞懂:Redis事务到底是什么?

Redis事务和MySQL事务初衷相似:把多条Redis命令打包成一组操作,执行过程中不会被其他客户端请求插队打断。 但两者本质差别巨大:MySQL完整支持ACID四大特性,Redis只是简易事务,原子性残缺、没有隔离级别、出错不会自动回滚。

Redis事务分为两大阶段:

  • 组队阶段(入队):执行MULTI开启事务,后续输入的所有命令不会立刻执行,全部存入事务队列,控制台返回QUEUED排队标识;中途不想提交可以用DISCARD清空整个队列,直接放弃本次事务。
  • 执行阶段(批量运行):输入EXEC提交事务,Redis会单线程串行执行队列里所有指令,执行期间阻塞其他客户端请求,保证命令不会穿插执行。
  • 二、四大核心命令 课堂实操案例

    1. MULTI + EXEC 正常提交事务

    流程:开启事务→批量写入命令→提交统一执行

    127.0.0.1> MULTI # 开启事务
    OK
    127.0.0.1(TX)> set username eric
    QUEUED
    127.0.0.1(TX)> set age 20
    QUEUED
    127.0.0.1(TX)> get username
    QUEUED
    127.0.0.1(TX)> EXEC # 提交,批量执行所有排队命令
    1) OK
    2) OK
    3) "eric"

    关键点:组队阶段无法查询数据,只有执行EXEC后,数据修改才会真正生效。

    2. DISCARD 放弃事务,清空队列

    写了一半发现逻辑错误,不想提交,直接丢弃所有排队指令,不会产生任何数据变更:

    127.0.0.1> MULTI
    OK
    127.0.0.1(TX)> set k1 v1
    QUEUED
    127.0.0.1(TX)> DISCARD # 放弃事务
    OK
    127.0.0.1> get k1
    (nil)

    3. WATCH 乐观锁,解决并发数据冲突

    这是Redis事务最核心的拓展命令,也是面试必考题。 作用:事务开启前监控一个或多个key,如果在EXEC执行前,这些key被其他客户端修改,本次事务直接作废,所有命令都不会执行。

    模拟场景:账户余额100,两个客户端同时发起扣款操作 客户端1操作:

    127.0.0.1> set balance 100
    OK
    127.0.0.1> WATCH balance # 监控余额key
    OK
    127.0.0.1> MULTI
    OK
    127.0.0.1(TX)> decrby balance 80
    QUEUED
    # 切到客户端执行扣款

    客户端2并发操作:

    127.0.0.1> decrby balance 50
    (integer) 50

    切回客户端1执行提交:

    127.0.0.1(TX)> EXEC
    (nil) # 返回nil,事务失效,防止超扣

    原理和数据库乐观锁版本号思路一致,完美解决并发修改覆盖问题。

    三、致命大坑:Redis事务不支持自动回滚

    90%初学者都会踩这个雷,分两种报错场景区分,期末必考:

    场景1:组队阶段语法错误 → 整个事务全部作废

    输入命令格式非法,入队时直接报错,后续执行EXEC会直接丢弃所有指令,一条都不执行。

    127.0.0.1> MULTI
    OK
    127.0.0.1(TX)> set k1 # 缺少value,语法错误,入队报错
    (error) ERR wrong number of arguments for 'set'
    127.0.0.1(TX)> set k2 v2
    QUEUED
    127.0.0.1(TX)> EXEC
    (error) EXECABORT Transaction discarded because of previous errors.
    # k1、k2均无数据

    场景2:组队无错误,执行时报错 → 正确命令正常生效,不会回滚

    命令语法没问题,但操作数据类型不匹配,执行失败时,其他正常执行的命令不会撤销。

    127.0.0.1> MULTI
    OK
    127.0.0.1(TX)> set num 100 # 正常指令
    QUEUED
    127.0.0.1(TX)> incr numstr # numstr不存在,无法自增,执行报错
    QUEUED
    127.0.0.1(TX)> set name eric # 正常指令
    QUEUED
    127.0.0.1(TX)> EXEC
    1) OK
    2) (error) ERR value is not an integer or out of range
    3) OK

    执行完成后,num=100、name=eric真实存入Redis,报错语句直接跳过,没有任何回滚操作。

    官方不做回滚的设计原因(面试标准答案)

  • Redis核心定位是高性能缓存,回滚机制会增加底层代码复杂度,大幅降低执行效率;
  • 语法、数据类型错误都属于开发阶段bug,上线前单元测试就能提前规避,不需要线上兜底回滚;
  • 如果需要完整原子执行、出错全部回滚的能力,优先使用Lua脚本。
  • 四、Redis事务 VS MySQL事务 ACID对比

    很多面试官会提问:Redis事务满足标准ACID吗?一张表讲清差异:

    四大特性MySQL事务Redis MULTI事务
    原子性(A) 完全满足,要么全部成功,失败全部回滚 残缺,执行过程不插队,但单条命令出错不会回滚其他操作
    一致性© 内置约束保障,异常自动修复数据合法 无内置机制,一致性需要业务代码自行维护
    隔离性(I) 提供四大隔离级别,读写互不干扰 无隔离级别概念,事务未提交的数据全局可见
    持久性(D) 提交后数据永久落盘 和事务无关,由RDB/AOF持久化配置控制

    Redis事务独有两个特性

  • 串行执行:EXEC运行期间,Redis单线程只处理当前事务队列,外部请求全部阻塞;
  • 无中间态:组队阶段的修改不会对外可见,只有提交后才生效。
  • 五、Redis事务适用&不适用场景

    适合使用

  • 批量缓存写入,多条命令需要连续执行、不被其他请求打断;
  • 简单并发控制:库存扣减、账户余额变更,搭配WATCH乐观锁;
  • 轻量统计类批量操作,对数据一致性要求不高。
  • 不推荐使用

  • 金融核心业务(转账、订单支付),零容忍数据错乱;
  • Redis集群环境,多键分属不同slot时,MULTI无法批量操作;
  • 复杂多分支业务逻辑,需要完整原子回滚;
  • 补充:需要强原子性统一用Lua脚本,脚本执行全程不可中断,出错不会半写入数据。

    六、期末/面试高频简答题汇总

  • Redis事务分为哪两个阶段? 答:组队阶段(MULTI入队,命令标记QUEUED)、执行阶段(EXEC批量执行),DISCARD命令可以直接丢弃未提交的事务队列。

  • WATCH命令的作用是什么? 答:实现Redis乐观锁,监控指定key;若事务提交前key被外部客户端修改,EXEC会返回nil,整个事务作废。

  • Redis事务为什么不支持回滚? 答:Redis主打高性能,回滚会增加底层复杂度;语法、类型错误属于开发bug,测试阶段可提前发现;需要完整原子操作推荐Lua脚本。

  • 两种事务报错处理有什么区别? 答:①入队时语法错误:整个事务直接作废;②组队无错、执行时报错:正常命令正常保存,错误语句跳过,不会回滚。

  • Redis事务完整支持ACID吗? 答:不支持。原子性残缺、无隔离级别,一致性需要业务代码维护,持久性由持久化配置决定,和事务本身无关。

  • 结尾小结

    之前一直用MySQL事务的固有思维写Redis代码,踩了不少坑,现在彻底分清两者的区别:Redis事务只是命令批量打包工具,不是传统关系型数据库的标准事务。 日常简单批量缓存操作、简单并发扣减场景,使用MULTI+WATCH完全够用;但支付、订单这类对数据一致性要求极高的业务,要么使用Lua脚本,要么把核心事务逻辑交给MySQL处理。

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » Redis事务学习笔记
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!