简介
MULTI
、EXEC
、DISCARD
和WATCH
是 Redis 事务相关的命令。事务可以一次执行多个命令, 并且带有以下两个重要的保证:
a)事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
b)事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。
原文地址: http://redis.cn/topics/transactions.html
用法
MULTI命令用于开启一个事务,它总是返回
OK
。 MULTI执行之后, 客户端可以继续向服务器发送任意多条命令, 这些命令不会立即被执行, 而是被放到一个队列中, 当 EXEC命令被调用时, 所有队列中的命令才会被执行。
另一方面, 通过调用DISCARD
, 客户端可以清空事务队列, 并放弃执行事务。
-
操作示例
EXEC命令的回复是一个数组, 数组中的每个元素都是执行事务中的命令所产生的回复。 其中, 回复元素的先后顺序和命令发送的先后顺序一致。
当客户端处于事务状态时, 所有传入的命令都会返回一个内容为 QUEUED
的状态回复(status reply), 这些被入队的命令将在 EXEC 命令被调用时执行。
事务中遇到异常如何处理
- 一般会遇到两种:
- 事务在执行 EXEC之前,入队的命令可能会出错。比如说,命令可能会产生语法错误(参数数量错误,参数名错误,等等),或者其他更严重的错误,比如内存不足(如果服务器使用
maxmemory
设置了最大内存限制的话)。 - 命令可能在 EXEC调用之后失败。举个例子,事务中的命令可能处理了错误类型的键,比如将列表命令用在了字符串键上面,诸如此类。
从 Redis 2.6.5 开始,服务器会对命令入队失败的情况进行记录,并在客户端调用 EXEC命令时,拒绝执行并自动放弃这个事务(当命令在入队时产生错误, 错误会立即被返回给客户端)。
在 EXEC命令执行之后所产生的错误, 并没有对它们进行特别处理: 即使事务中有某个/某些命令在执行时产生了错误, 事务中的其他命令仍然会继续执行。
最重要的是记住这样一条, 即使事务中有某条/某些命令执行失败了, 事务队列中的其他命令仍然会继续执行 —— Redis 不会停止执行事务中的命令。
为什么 Redis 不支持回滚?
- Redis 命令只会因为错误的语法而失败(并且这些问题不能在入队时发现),或是命令用在了错误类型的键上面:这也就是说,从实用性的角度来说,失败的命令是由
编程错误
造成的,而这些错误应该在开发的过程中被发现,而不应该出现在生产环境中。 - 因为不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速。
放弃事务
当执行DISCARD命令时, 事务会被放弃, 事务队列会被清空, 并且客户端会从事务状态中退出。
WATCH可以实现乐观锁
被 WATCH
的键会被监视,监控这些键是否被改动过了。 如果有至少一个被监视的键在 EXEC
执行之前被修改了, 那么整个事务都会被取消, EXEC
返回nil-reply
来表示事务已经失败。
上图中两个client端,分别开启事务,且分别将命令放入队列,但是client2有对k1的监控,假如两个客户端同时执行,但client1先执行了exec操作,此时client2的事务会取消。
————————————————————
坐标帝都,白天上班族,晚上是知识的分享者
如果读完觉得有收获的话,欢迎点赞加关注