Redis实践篇(ACID的事务机制)

103 阅读3分钟

Redis如何实现事务?

事务的执行过程包含三个步骤,Redis 提供了 MULTI、EXEC 两个命令来完成这三个步骤。

  1. 第一步,客户端要使用一个命令显式地表示一个事务的开启。在 Redis 中,这个命令就是MULTI。
  2. 第二步,客户端把事务中本身要执行的具体操作(例如增删改数据)发送给服务器端。这 些操作就是 Redis 本身提供的数据读写命令,例如 GET、SET 等。不过,这些命令虽然被 客户端发送到了服务器端,但 Redis 实例只是把这些命令暂存到一个命令队列中,并不会 立即执行。
  3. 第三步,客户端向服务器端发送提交事务的命令,让数据库实际执行第二步中发送的具体 操作。Redis 提供的 EXEC 命令就是执行事务提交的。当服务器端收到 EXEC 命令后,才 会实际执行命令队列中的所有命令。

好了,通过使用 MULTI 和 EXEC 命令,我们可以实现多个操作的共同执行,但是这符合事 务要求的 ACID 属性吗?

原子性

如果事务正常执行,没有发生任何错误,那么,MULTI 和 EXEC 配合使用,就可以保证多 个操作都完成。但是,如果事务执行发生错误了,原子性还能保证吗?

  1. 第一种情况是,在执行 EXEC 命令前,客户端发送的操作命令本身就有错误(比如语法错 误,使用了不存在的命令),在命令入队时就被 Redis 实例判断出来了。此时,能够保障原子性,因为后续的命令都会被放弃。
  2. 第二种情况,错误发生在命令执行时,虽然 Redis 会对错误命令报错,但还是会把正确的命令执 行完。在这种情况下,事务的原子性就无法得到保证了。

一致性

  1. 命令在执行前报错,所以命令都不会被执行,一致性可以保障;
  2. 命令执行中报错,报错的命令不被执行,正确的命令会被执行,严格来说,业务的一致性被破坏了。

隔离性

  1. 并发操作在 EXEC 命令前执行,此时,隔离性的保证要使用 WATCH 机制来实现,否则隔离性无法保证;
  2. 并发操作在 EXEC 命令后执行,此时,隔离性可以保证,因为只有一个线程执行。

WATCH 机制的作用是,在事务执行前,监控一个或多个键的值变化情况,当事务调用EXEC 命令执行时,WATCH 机制会先检查监控的键是否被其它客户端修改了。如果修改了,就放弃事务执行,避免事务的隔离性被破坏。然后,客户端可以再次执行事务,此时,如果没有并发修改事务数据的操作了,事务就能正常执行,隔离性也得到了保证。

持久性

数据是否持久化保存完全取决于 Redis 的持久化配置模式。

  1. 如果是RDB模式,,那么,在一个事务执行后,而下一次的 RDB 快照还未执行前,如果发生了实例宕机,这种情况下,事务修改的数据也是不能保证持久化的。
  2. 如果是AOF模式,因为 AOF 模式的三种配置选项 no、everysec 和 always都会存在数据丢失的情况,所以,事务的持久性属性也还是得不到保证。