2026-01-19 07:39:38
Redis支持事务,但属于弱事务,不具备ACID特性中的隔离性,且多条命令不保证原子性。其事务本质是一组命令的集合,通过MULTI/EXEC/DISCARD命令实现,而乐观锁通过WATCH命令实现。以下是具体说明:
事务(MULTI/EXEC/DISCARD)核心特性
弱事务性:Redis事务没有隔离级别,事务中的命令不会立即执行,而是先序列化存入队列,执行时按顺序处理。
非原子性:单条命令原子性由Redis保证,但事务内多条命令若部分失败,不会回滚已执行的命令。
执行流程:
开启事务:MULTI 命令标记事务开始。
命令入队:后续命令依次加入队列,返回QUEUED状态。
执行事务:EXEC 命令触发队列中所有命令按顺序执行。
取消事务:DISCARD 命令清空队列并退出事务模式。
示例场景
正常执行:
127.0.0.1:6379> MULTIOK127.0.0.1:6379> SET name wuxlQUEUED127.0.0.1:6379> SET age 30QUEUED127.0.0.1:6379> EXEC1) OK2) OK取消事务:
127.0.0.1:6379> MULTIOK127.0.0.1:6379> SET name wuxlQUEUED127.0.0.1:6379> DISCARDOK127.0.0.1:6379> GET name(nil)错误处理
编译错误:命令入队时因语法错误被拒绝,后续EXEC会失败并清空队列。
127.0.0.1:6379> MULTIOK127.0.0.1:6379> GET # 错误命令(error) ERR wrong number of arguments for 'get' command127.0.0.1:6379> EXEC(error) EXECABORT Transaction discarded because of previous errors.运行时错误:命令入队时正确,但执行时因类型不匹配等逻辑错误失败,不影响其他命令。
127.0.0.1:6379> MULTIOK127.0.0.1:6379> SET name wuxlQUEUED127.0.0.1:6379> INCR name # 对字符串执行自增操作QUEUED127.0.0.1:6379> EXEC1) OK2) (error) ERR value is not an integer or out of range核心机制
监控键值:WATCH 命令监视一个或多个键,若事务执行前被其他客户端修改,则事务中断。
无阻塞设计:相比悲观锁(如MySQL的行锁),乐观锁通过版本检查实现并发控制,避免性能损耗。
应用场景
转账模拟:
初始化数据:
127.0.0.1:6379> SET acc1 1000OK127.0.0.1:6379> SET acc2 0OK客户端A监控并开启事务:
127.0.0.1:6379> WATCH acc1OK127.0.0.1:6379> MULTIOK127.0.0.1:6379> DECRBY acc1 100QUEUED127.0.0.1:6379> INCRBY acc2 100QUEUED客户端B修改数据:
127.0.0.1:6379> INCRBY acc1 1000(integer) 2000客户端A执行事务:
127.0.0.1:6379> EXEC(nil) # 事务因acc1被修改而失败注意事项
监控失效条件:WATCH 的键若在EXEC前被修改(无论由哪个客户端触发),事务均会失败。
重试机制:事务失败后需重新获取数据并重试,适合低冲突场景。