深入理解Redis系列之事务

事务命令

Redis通过MULTI、EXEC、WATCH等命令来实现事务

MULTI //事务开始

SET "name" "test" //do something
...

EXEC //提交事务

WATCH "name" //WATCH监视
DISCARD //丢弃事务

事务执行流程

在这里插入图片描述

事务命令队列

在这里插入图片描述

WATCH命令

WATCH 命令可以为 Redis 事务提供 check-and-set (CAS)行为。

在这里插入图片描述

Redis事务到底是不是原子性的?

官方文档对事务的定义:

  • 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
  • 事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。EXEC 命令负责触发并执行事务中的所有命令:如果客户端在使用 MULTI 开启了一个事务之后,却因为断线而没有成功执行 EXEC ,那么事务中的所有命令都不会被执行。另一方面,如果客户端成功在开启事务之后执行 EXEC ,那么事务中的所有命令都会被执行。

官方认为Redis事务是一个原子操作,这是站在执行与否的角度考虑的。但是从ACID原子性定义来看,严格意义上讲Redis事务是非原子型的,因为在命令顺序执行过程中,一旦发生命令执行错误Redis是不会停止执行然后回滚数据。

为什么 Redis 不支持回滚(roll back)

以下是这种做法的优点:

  • Redis 命令只会因为错误的语法而失败(并且这些问题不能在入队时发现),或是命令用在了错误类型的键上面:这也就是说,从实用性的角度来说,失败的命令是由编程错误造成的,而这些错误应该在开发的过程中被发现,而不应该出现在生产环境中。
  • 因为不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速。

对于官方的这种理由有一个普遍的反对观点:程序有bug怎么办?但其实回归不能解决程序的bug,比如某位粗心的程序员计划更新键A,实际上最后更新了键B,回滚机制是没法解决这种人为错误的。正因为这种人为的错误不太可能进入生产系统,所以官方在设计Redis时选用更加简单和快速的方法,没有实现回滚的机制。

参考:
《Redis开发与运维》
《Redis设计与实现》
https://mp.weixin.qq.com/s/GwjQalQ9ZkBbTBtEKpbkMw

posted @ 2020-12-31 10:06  曹自标  阅读(97)  评论(0编辑  收藏  举报