抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >
  • 需要明确最重要一点就是,Redis的事务不保证原子性,事务出错不回滚

  • 数据库的事务定义特点是“一系列程序执行单元,要么完全地执行,要么完全地不执行”

  • 但是在Redis中的事务机制在某些地方跟数据库还是存在明显的不同

Github issues:https://github.com/littlejoyo/Blog/issues/

1.Redis事务机制

  • Redis事务会将所有命令放入一个命令队列中,再由队列中执行命令。

  • Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证:

    • 批量操作在发送 EXEC 命令前被放入队列缓存。

    • 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。

    • 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。

  • 一个事务从开始到执行会经历以下三个阶段:

    • 开始事务。
    • 命令入队。
    • 执行事务。

2. Redis事务实例

  • 先以 MULTI 开始一个事务

  • 然后将多个命令入队到事务中

  • 最后由 EXEC 命令触发事务, 一并执行事务中的所有命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

redis 127.0.0.1:6379> MULTI
OK
redis 127.0.0.1:6379> SET book-name "Mastering C++ in 21 days"
QUEUED
redis 127.0.0.1:6379> GET book-name
QUEUED
redis 127.0.0.1:6379> SADD tag "C++" "Programming" "Mastering Series"
QUEUED
redis 127.0.0.1:6379> SMEMBERS tag
QUEUED
redis 127.0.0.1:6379> EXEC
1) OK
2) "Mastering C++ in 21 days"
3) (integer) 3
4) 1) "Mastering Series"
2) "C++"
3) "Programming"

3.Redis事务的注意点

  • 单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制

  • 所以 Redis 事务的执行并不是原子性的

  • 事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。

4.讨论Redis事务的ACID

Redis 的事务保证了 ACID 中的一致性(C)和隔离性(I),但并不保证原子性(A)和持久性(D)。

  • 原子性(一个事务所有操作要么全部成功,要么全部失败)

    • redis的单个命令是原子性的
    • 但是事务中的的redis命令,就算后面的命令失败/终止了(比如KILL进程,主机宕机等),此时事务失败,前面执行的命令也不会回滚。
  • 一致性

    (1)不正确入队命令的事务不会被执行,不会影响数据库的一致性

    (2)命令执行中的错误,将错误包含在事务结果中,不会中断事务,不影响已执行结果,也不影响后面命令的执行,对事务的一致性也没有影响。

    (3)进程终结

    内存模式:如果 Redis 没有采取任何持久化机制,那么重启之后的数据库总是空白的,所以数据总是一致的。

    RDB 模式:在执行事务时,Redis 不会中断事务去执行保存 RDB 的工作,只有在事务执行之后,保存 RDB 的工作才有可能开始。所以当 RDB 模式下的 Redis 服务器进程在事务中途被杀死时,事务内执行的命令,不管成功了多少,都不会被保存到 RDB 文件里。恢复数据库需要使用现有的 RDB 文件,而这个 RDB 文件的数据保存的是最近一次的数据库快照(snapshot),所以它的数据可能不是最新的,但只要 RDB 文件本身没有因为其他问题而出错,那么还原后的数据库就是一致的。

    AOF 模式:因为保存 AOF 文件的工作在后台线程进行,所以即使是在事务执行的中途,保存 AOF 文件的工作也可以继续进行,因此,根据事务语句是否被写入并保存到 AOF 文件,有以下两种情况发生:

    1)如果事务语句未写入到 AOF 文件,或 AOF 未被 SYNC 调用保存到磁盘,那么当进程被杀死之后,Redis 可以根据最近一次成功保存到磁盘的 AOF 文件来还原数据库,只要 AOF 文件本身没有因为其他问题而出错,那么还原后的数据库总是一致的,但其中的数据不一定是最新的。

    2)如果事务的部分语句被写入到 AOF 文件,并且 AOF 文件被成功保存,那么不完整的事务执行信息就会遗留在 AOF 文件里,当重启 Redis 时,程序会检测到 AOF 文件并不完整,Redis 会退出,并报告错误。需要使用 redis-check-aof 工具将部分成功的事务命令移除之后,才能再次启动服务器。还原之后的数据总是一致的,而且数据也是最新的(直到事务执行之前为止)。

  • 隔离性

    • Redis 是单进程程序,并且它保证在执行事务时,不会对事务进行中断,事务可以运行直到执行完所有事务队列中的命令为止。
    • 因此,Redis 的事务是总是带有隔离性的。
  • 持久性

    由redis的持久化模式决定:

    • 内存模式-无持久化

    • RDB模式:服务器可能在事务执行之后、RDB 文件更新之前的这段时间失败,所以 RDB 模式下的 Redis 事务也是不持久的。

    • AOF模式:后台每秒fsync策略,不是主线程阻塞执行,如果在保存时宕机,可能有一秒数据丢失,也非持久的。

微信公众号

扫一扫关注Joyo说公众号,共同学习和研究开发技术。

weixin-a

评论