一、Redis事务基础介绍Redis的事务是一套轻量级的命令批量执行机制核心特性可以总结为4点核心实现依赖4个命令通过MULTI、EXEC、DISCARD和WATCH这四个命令完整完成事务的全流程操作。事务的原子性保障对象Redis本身的单个命令都是原子性的因此它的事务保障的是一组命令集合的执行特性。执行逻辑Redis会将事务内的命令集合序列化确保这一组命令可以连续、不被其他外部请求打断地执行。特殊限制和传统关系型数据库事务不同Redis不支持事务回滚操作。二、相关核心命令命令作用返回值/表现MULTI开启事务块。后续命令会被放入队列暂存不会立即执行。OKEXEC执行事务块中的所有命令。按入队顺序依次执行并返回每个命令的结果。数组包含各命令的执行结果DISCARD取消事务。清空当前事务队列中的所有命令退出事务状态。OKWATCH监视一个或多个键。用于实现乐观锁若事务执行前被监视的键被修改则事务执行失败。OKUNWATCH取消所有由 WATCH 命令监视的键。通常在 EXEC 或 DISCARD 后自动执行也可手动调用。OK1MULTI事务的起始命令这是事务的起始命令相关说明如下作用用于标记一个事务块的开始执行逻辑客户端发送MULTI之后Redis不会立即执行后续发来的命令而是把这些命令逐个放入命令队列中等待后续使用EXEC命令一次性原子化地执行整个队列里的命令序列。语法直接输入MULTI即可触发。2. EXEC 命令核心作用它是事务的「提交执行」指令执行逻辑会一次性把之前通过MULTI开启事务后、陆续放入队列的所有命令按入队顺序全部执行完毕。执行完成后客户端就会自动退出事务状态恢复到正常的Redis连接模式。语法直接输入 EXEC 即可调用。补充说明执行后会返回一个结果数组数组里的每一项对应事务队列里每一条命令的执行结果。3. DISCARD 命令核心作用它是事务的「取消/回滚」指令执行逻辑会直接清空当前事务队列里所有暂存的命令相当于放弃本次事务的所有操作执行后客户端同样会恢复到正常连接状态。语法直接输入 DISCARD 即可调用。补充说明如果之前使用了WATCH监听了键执行DISCARD的同时也会自动释放所有被监视的键取消监听状态。4. WATCH 命令核心作用它是Redis实现「乐观锁」的核心指令执行逻辑当事务需要满足特定条件才能执行时就可以用WATCH把指定的键标记为受监控状态。如果在你提交EXEC之前这些被监控的键被其他客户端修改过那么本次事务就会直接执行失败所有队列里的命令都不会生效以此避免并发场景下的数据冲突。语法支持同时监听多个键格式为 WATCH key [key ...]。典型场景比如秒杀库存扣减、余额条件修改这类需要“先检查条件、再执行操作”的并发场景用WATCH就可以避免超卖、数据不一致的问题。三命令复习multi开启事务开启事务之后讲要操作的命令都放到了QUEUEDqueued队列里然后通过EXEC命令一起提交。对于WATCH命令开启了事务没有提交这时候又有一个客户端进来操作然后前面那个开启事务的提交发现提交成功。这时候看k1被改成了v111。这时候出现另一种情况a线程来修改时候我希望没有其他线程来干扰我这时候开启 监听WATCH。。上面这个操作很顺利没有其他线程干扰也就操作成功。实际情况下可能会收到其他线程干扰下面的命令还没有提交这时候另一个终端连上来执行了k1的修改。此时A线程提交此时提交失败出现了 nilget k1 获取了别人修改过的值四、事务执行流程Redis 事务分为两个阶段组队阶段和执行阶段。1. 组队阶段入队执行MULTI后客户端进入事务状态。随后发送的命令如SET,INCR等不会立即执行而是被放入一个临时队列中。服务器对每个入队命令返回QUEUED表示命令已接收并排队。2. 执行阶段提交执行EXEC后Redis 会原子性地按顺序执行队列中的所有命令。在执行过程中其他客户端的命令请求不会插入到当前事务的命令序列中保证了隔离性。EXEC返回一个数组数组元素对应事务中每个命令的执行结果。3. 取消事务在EXEC之前若执行DISCARD则清空队列放弃本次事务所有命令均不执行。五、错误处理机制Redis 事务的错误处理分为两种情况这是其与 MySQL 事务最大的区别之一1. 语法错误组队阶段失败场景命令格式错误、参数数量不对等如INCR key1 key2。结果从 Redis 2.6.5 版本开始如果入队时检测到语法错误执行EXEC时会直接报错整个事务中的所有命令都不会执行。注意早期版本可能会忽略错误命令只执行正确的但现代版本已统一为全部拒绝。2. 运行错误执行阶段失败场景命令语法正确但逻辑错误如对字符串类型的 Key 执行列表操作LPUSH或对不存在的 Key 进行特定运算。结果没有回滚机制。出错的命令会返回错误信息但事务中其他正确的命令依然会继续执行。原因Redis 设计哲学追求简单高效若支持回滚需记录中间状态会增加复杂度和性能开销。因此开发者需在代码层面保证命令逻辑的正确性。六、乐观锁与 WATCH 机制由于 Redis 事务不支持回滚若需解决并发冲突如秒杀超卖通常结合WATCH实现乐观锁。工作原理监视使用WATCH key监视目标键。组队执行MULTI开启事务编写业务逻辑命令。检查与执行执行EXEC时Redis 会检查被监视的键是否在WATCH之后、EXEC之前被其他客户端修改过。若未修改正常执行事务。若已修改事务执行失败返回nil所有命令不执行。示例场景# 客户端 A 127.0.0.1:6379 WATCH stock # 监视库存 OK 127.0.0.1:6379 MULTI # 开启事务 OK 127.0.0.1:6379(TX) DECR stock # 扣减库存 QUEUED 127.0.0.1:6379(TX) EXEC # 提交事务 1) (integer) 99 # 执行成功 # 客户端 B (在 A 执行 EXEC 前修改了 stock) 127.0.0.1:6379 SET stock 100 # 修改了被监视的键 OK # 此时客户端 A 再执行 EXEC 127.0.0.1:6379(TX) EXEC (nil) # 返回 nil事务失败需重试七、总结与注意事项非原子性狭义Redis 事务不保证“要么全成功要么全失败”的回滚原子性仅保证执行过程的隔离性和顺序性。无隔离级别Redis 是单线程模型事务执行期间不会被其他命令打断因此不存在传统数据库的脏读、不可重复读等问题无需设置隔离级别。适用场景适用于需要批量执行、防止命令插队的场景。若需强一致性或复杂条件判断建议使用 Lua 脚本因为 Lua 脚本在 Redis 中原子执行且支持逻辑判断功能更强大。
redis事务命令复习
一、Redis事务基础介绍Redis的事务是一套轻量级的命令批量执行机制核心特性可以总结为4点核心实现依赖4个命令通过MULTI、EXEC、DISCARD和WATCH这四个命令完整完成事务的全流程操作。事务的原子性保障对象Redis本身的单个命令都是原子性的因此它的事务保障的是一组命令集合的执行特性。执行逻辑Redis会将事务内的命令集合序列化确保这一组命令可以连续、不被其他外部请求打断地执行。特殊限制和传统关系型数据库事务不同Redis不支持事务回滚操作。二、相关核心命令命令作用返回值/表现MULTI开启事务块。后续命令会被放入队列暂存不会立即执行。OKEXEC执行事务块中的所有命令。按入队顺序依次执行并返回每个命令的结果。数组包含各命令的执行结果DISCARD取消事务。清空当前事务队列中的所有命令退出事务状态。OKWATCH监视一个或多个键。用于实现乐观锁若事务执行前被监视的键被修改则事务执行失败。OKUNWATCH取消所有由 WATCH 命令监视的键。通常在 EXEC 或 DISCARD 后自动执行也可手动调用。OK1MULTI事务的起始命令这是事务的起始命令相关说明如下作用用于标记一个事务块的开始执行逻辑客户端发送MULTI之后Redis不会立即执行后续发来的命令而是把这些命令逐个放入命令队列中等待后续使用EXEC命令一次性原子化地执行整个队列里的命令序列。语法直接输入MULTI即可触发。2. EXEC 命令核心作用它是事务的「提交执行」指令执行逻辑会一次性把之前通过MULTI开启事务后、陆续放入队列的所有命令按入队顺序全部执行完毕。执行完成后客户端就会自动退出事务状态恢复到正常的Redis连接模式。语法直接输入 EXEC 即可调用。补充说明执行后会返回一个结果数组数组里的每一项对应事务队列里每一条命令的执行结果。3. DISCARD 命令核心作用它是事务的「取消/回滚」指令执行逻辑会直接清空当前事务队列里所有暂存的命令相当于放弃本次事务的所有操作执行后客户端同样会恢复到正常连接状态。语法直接输入 DISCARD 即可调用。补充说明如果之前使用了WATCH监听了键执行DISCARD的同时也会自动释放所有被监视的键取消监听状态。4. WATCH 命令核心作用它是Redis实现「乐观锁」的核心指令执行逻辑当事务需要满足特定条件才能执行时就可以用WATCH把指定的键标记为受监控状态。如果在你提交EXEC之前这些被监控的键被其他客户端修改过那么本次事务就会直接执行失败所有队列里的命令都不会生效以此避免并发场景下的数据冲突。语法支持同时监听多个键格式为 WATCH key [key ...]。典型场景比如秒杀库存扣减、余额条件修改这类需要“先检查条件、再执行操作”的并发场景用WATCH就可以避免超卖、数据不一致的问题。三命令复习multi开启事务开启事务之后讲要操作的命令都放到了QUEUEDqueued队列里然后通过EXEC命令一起提交。对于WATCH命令开启了事务没有提交这时候又有一个客户端进来操作然后前面那个开启事务的提交发现提交成功。这时候看k1被改成了v111。这时候出现另一种情况a线程来修改时候我希望没有其他线程来干扰我这时候开启 监听WATCH。。上面这个操作很顺利没有其他线程干扰也就操作成功。实际情况下可能会收到其他线程干扰下面的命令还没有提交这时候另一个终端连上来执行了k1的修改。此时A线程提交此时提交失败出现了 nilget k1 获取了别人修改过的值四、事务执行流程Redis 事务分为两个阶段组队阶段和执行阶段。1. 组队阶段入队执行MULTI后客户端进入事务状态。随后发送的命令如SET,INCR等不会立即执行而是被放入一个临时队列中。服务器对每个入队命令返回QUEUED表示命令已接收并排队。2. 执行阶段提交执行EXEC后Redis 会原子性地按顺序执行队列中的所有命令。在执行过程中其他客户端的命令请求不会插入到当前事务的命令序列中保证了隔离性。EXEC返回一个数组数组元素对应事务中每个命令的执行结果。3. 取消事务在EXEC之前若执行DISCARD则清空队列放弃本次事务所有命令均不执行。五、错误处理机制Redis 事务的错误处理分为两种情况这是其与 MySQL 事务最大的区别之一1. 语法错误组队阶段失败场景命令格式错误、参数数量不对等如INCR key1 key2。结果从 Redis 2.6.5 版本开始如果入队时检测到语法错误执行EXEC时会直接报错整个事务中的所有命令都不会执行。注意早期版本可能会忽略错误命令只执行正确的但现代版本已统一为全部拒绝。2. 运行错误执行阶段失败场景命令语法正确但逻辑错误如对字符串类型的 Key 执行列表操作LPUSH或对不存在的 Key 进行特定运算。结果没有回滚机制。出错的命令会返回错误信息但事务中其他正确的命令依然会继续执行。原因Redis 设计哲学追求简单高效若支持回滚需记录中间状态会增加复杂度和性能开销。因此开发者需在代码层面保证命令逻辑的正确性。六、乐观锁与 WATCH 机制由于 Redis 事务不支持回滚若需解决并发冲突如秒杀超卖通常结合WATCH实现乐观锁。工作原理监视使用WATCH key监视目标键。组队执行MULTI开启事务编写业务逻辑命令。检查与执行执行EXEC时Redis 会检查被监视的键是否在WATCH之后、EXEC之前被其他客户端修改过。若未修改正常执行事务。若已修改事务执行失败返回nil所有命令不执行。示例场景# 客户端 A 127.0.0.1:6379 WATCH stock # 监视库存 OK 127.0.0.1:6379 MULTI # 开启事务 OK 127.0.0.1:6379(TX) DECR stock # 扣减库存 QUEUED 127.0.0.1:6379(TX) EXEC # 提交事务 1) (integer) 99 # 执行成功 # 客户端 B (在 A 执行 EXEC 前修改了 stock) 127.0.0.1:6379 SET stock 100 # 修改了被监视的键 OK # 此时客户端 A 再执行 EXEC 127.0.0.1:6379(TX) EXEC (nil) # 返回 nil事务失败需重试七、总结与注意事项非原子性狭义Redis 事务不保证“要么全成功要么全失败”的回滚原子性仅保证执行过程的隔离性和顺序性。无隔离级别Redis 是单线程模型事务执行期间不会被其他命令打断因此不存在传统数据库的脏读、不可重复读等问题无需设置隔离级别。适用场景适用于需要批量执行、防止命令插队的场景。若需强一致性或复杂条件判断建议使用 Lua 脚本因为 Lua 脚本在 Redis 中原子执行且支持逻辑判断功能更强大。