说说 Redis 事务( 三 )

redis-check-aof工具检测 AOF 日志文件,可以把未完成的事务操作从 AOF 文件中去除 。这样一来,使用 AOF 文件恢复实例后,事务操作不会被再执行,从而保证了原子性 。若使用的 RDB 模式,最新的 RDB 快照是在 EXEC 执行之前生成的,使用快照恢复之后,事务中的命令也都没有执行,从而保证了原子性 。若 Redis 没有开启持久化,则重启后内存中的数据全部丢失,也就谈不上原子性了 。

  • 一致性(C)
一致性指的是事务执行前后,数据符合数据库的定义和要求 。这点在 Redis 事务中是满足的,不论是发生语法错误还是运行时错误,错误的命令均不会被执行 。
  1. EXEC 执行之前,入队报错(实例分析中的语法错误)
事务会放弃执行,故可以保证一致性 。
  1. EXEC 执行之后,实际执行时报错(实例分析中的运行时错误)
错误的命令不会被执行,正确的命令被执行,一致性可以保证 。
  1. EXEC 执行时,实例宕机
若 Redis 没有开启持久化,实例宕机重启后,数据都没有了,数据是一致的 。若配置了 RDB 方式,RDB 快照不会在事务执行时执行 。所以,若事务执行到一半,实例发生了故障,此时上一次 RDB 快照中不会包含事务所做的修改,而下一次 RDB 快照还没有执行,实例重启后,事务修改的数据会丢失,数据是一致的 。若事务已经完成,但新一次的 RDB 快照还没有生成,那事务修改的数据也会丢失,数据也是一致的 。若配置了 AOF 方式 。当事务操作还没被记录到 AOF 日志时,实例就发生故障了,使用 AOF 日志恢复后数据是一致的 。若事务中的只有部分操作被记录到 AOF 日志,可以使用 redis-check-aof清除事务中已经完成的操作,数据库恢复后数据也是一致的 。
  • 隔离性(I)
    1. 并发操作在 EXEC 执行前,隔离性需要通过 WATCH 机制来保证
    2. 并发操作在 EXEC 命令之后,隔离性可以保证
情况 a可以参考前面的实例分析 WATCH 命令的使用 。情况 b,由于 Redis 是单线程执行命令,EXEC 命令执行后,Redis 会保证先把事务队列中的所有命令执行完之后再执行之后的命令 。
  • 持久性(D)
若 Redis 没有开启持久化,那么就是所有数据都存储在内存中,一旦重启,数据就会丢失,因此此时事务的持久性是肯定无法得到保证的 。若 Redis 开启了持久化,当实例宕机重启,还是会有可能丢失数据,因此也并能完全保证持久性 。因此,我们可以说 Redis 事务无法一定保证持久性,仅在特殊的情况下,可以保证持久性 。
关于 Redis 在开启持久化之后,为啥还会丢失数据,笔者会单独整理一篇 Redis 持久化与主从相关的文章来介绍,此处简单说下 。如果配置了 RDB 模式,在一个事务执行后,下一次 RDB 快照还未执行前,Redis 实例发生了宕机,数据就会丢失、如果配置了 AOF 模式,而 AOF 模式的三种配置选项 no,everysec,always 也都可能会产生数据丢失的情况 。
总结一下,Redis 事务对 ACID 的支持情况:
  • 具备一定的原子性,但不支持回滚
  • 满足一致性
  • 满足隔离性
  • 无法保证持久性
Redis 事务为什么不支持回滚看一下官网的的说明:
【说说 Redis 事务】What about rollbacks?Redis does not support rollbacks of transactions since supporting rollbacks would have a significant impact on the simplicity and performance of Redis.

说说 Redis 事务

经验总结扩展阅读