一、什么是Redis事务?
1.1 Redis事务是一组一次性、顺序性、排他性执行的Redis命令集合。事务会将多个命令打包,一次性发送给Redis服务端执行,执行过程中不会被其他客户端命令插队,保证批量命令的执行完整性。
1.2 核心特性:
原子性(部分支持):命令入队前报错,全部不执行;命令入队后执行报错,成功的命令不会回滚(核心区别于MySQL)
一致性(支持):事务执行前后,数据库数据合法、完整,无非法数据
补充:另外一种说法是redis不支持一致性,因为如果在事务执行的过程中有命令执行失败就会引起不一致的情况(以MySQL的一致性为标准)
隔离性(支持):事务执行过程中,其他客户端无法插入命令,串行执行
补充:同样有另外一种说法是redis不支持隔离性,因为redis是单线程来执行命令(同样以MySQL隔离性为标准)
持久性(不支持):事务执行成功后,数据是否持久化由Redis持久化策略决定,事务本身不保证持久化
1.3 适用场景
1,多命令批量执行,避免穿插干扰,
2,简单的数据一致性控制,无需复杂事务回滚的场景
3,高频轻量批量操作,追求执行效率(减少网络IO次数)
二、Redis事务核心命令详解
Redis事务仅依赖4个核心命令,所有事务操作均围绕这四个命令完成,无额外复杂配置。
命令 | 作用 | 使用时机 |
|---|---|---|
MULTI | 开启事务,标记事务起始位置 | 所有批量命令执行前 |
EXEC | 提交事务,执行队列中所有缓存命令 | 所有命令入队完成后 |
DISCARD | 取消事务,清空命令队列,退出事务状态 | 入队阶段发现错误、主动放弃事务 |
WATCH | 监听Key,实现乐观锁,Key被修改则事务失效 | 需要防并发修改、保证数据版本一致 |
2.1 基础执行流程
完整事务执行分为三个阶段,是理解所有原理的基础:
开启事务(MULTI):客户端从普通状态切换为事务状态,后续所有命令不立即执行,全部存入事务命令队列
命令入队:依次执行读写命令,Redis仅校验命令语法,不执行逻辑,合法命令入队,非法命令直接报错
提交/回滚:EXEC执行所有队列命令;DISCARD清空队列、终止事务
三、Redis事务核心原理
3.1 事务底层队列机制
Redis服务端为每个客户端维护一个独立事务命令队列:
1,执行MULTI后,客户端状态标记为TX(事务模式)
2,TX模式下,所有合法命令仅入队、不执行,返回QUEUED
3,收到EXEC指令后,服务端串行、一次性执行队列所有命令,期间不处理其他客户端请求
4,执行完毕后,清空队列,客户端退出事务模式,恢复普通状态
3.2 WATCH乐观锁原,
Redis事务本身无锁机制,默认无法解决并发修改问题,WATCH命令是Redis事务实现并发控制的唯一方式,基于乐观锁机制实现。
3.2.1 执行逻辑
客户端通过WATCH key1 key2... 监听指定Key
Redis记录当前Key的版本
事务提交EXEC前,校验监听的Key是否被其他客户端修改
若Key未被修改:正常执行事务;若已被修改:事务直接放弃执行,返回nil
3.2.2 取消监听
执行UNWATCH可手动取消所有Key监听;事务执行/取消后,监听会自动失效。
3.3 事务隔离级别
Redis事务仅支持串行化隔离级别:事务执行期间,所有命令独占服务端,其他客户端命令必须等待当前事务执行完毕后才能执行,完全避免幻读、脏读、不可重复读问题。
缺点:大事务会阻塞主线程,导致Redis性能下降,因此Redis事务禁止批量执行大量命令。
四、Redis事务两大核心坑点
Redis事务的所有问题都源于不满足严格原子性,分为两种报错场景,务必区分。
4.1 入队阶段报错——全部不执行
事务开启后,命令语法错误、参数错误,入队失败,EXEC提交时,整个事务全部失效,无任何命令执行。
原因:Redis检测到入队阶段存在非法命令,直接标记事务失效,提交时清空队列。
4.2 执行阶段报错——部分执行、无法回滚
命令语法合法,但逻辑执行报错(如对字符串执行自增、哈希字段操作普通Key),命令正常入队,EXEC执行时,正确命令正常执行,错误命令报错,无回滚。
核心总结:Redis事务不支持事务回滚,必须自行处理事务中的逻辑异常,这是与MySQL事务最大的区别。
五、Redis事务 和 Lua脚本 对比
在需要原子性、并发控制的场景中,Lua脚本是Redis事务的进阶替代方案,二者差异极大。
对比维度 | Redis事务 | Lua脚本 |
|---|---|---|
原子性 | 部分原子性,执行报错不回滚 | 完整原子性,脚本报错全部回滚 |
并发控制 | 依赖WATCH乐观锁,需重试机制 | 脚本独占执行,天然杜绝并发干扰 |
灵活性 | 仅支持简单命令批量执行 | 支持逻辑判断、循环、复杂运算 |
性能 | 多次命令入队,轻微性能损耗 | 单次脚本执行,网络IO最少,性能更高 |
适用场景 | 简单批量操作、低并发场景 | 高并发、复杂逻辑、强原子性场景 |
六、面试高频总结
Redis事务是否支持回滚?不支持。仅入队语法错误整体失效,执行逻辑错误会部分执行,无回滚机制。
Redis事务的ACID特性?支持一致性、隔离性;部分支持原子性;不支持持久性。
WATCH命令原理?基于乐观锁,监听Key版本,并发修改则事务失效。
事务和Lua脚本区别?Lua具备完整原子性、更高性能、更强灵活性,是高并发场景最优解。
Redis事务隔离级别?串行化,执行过程独占线程,无脏读、幻读。
七、总结
Redis事务的核心价值是批量命令串行无干扰执行、减少网络IO,但受限于Redis轻量化设计,不具备关系型数据库的完整原子性和回滚能力。对于简单批量操作可直接使用原生事务+WATCH实现,高并发、强一致性场景优先选用Lua脚本。