Redis RDB和AOF命令SAVE和BGSAVE BGREWRITEAOF在执行时问题区别

                            声明:摘抄自Redis 设计与实现。感谢分享。尊重原著,致谢。


RDB和AOF特点:(Redis 持久化

    RDB:保存为dump.rdb 文件

        

save 60 1000

  • RDB在保存RDB文件时父进程唯一需要做的就是fork出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的性能.
  • 与AOF相比,在恢复大的数据集的时候,RDB方式会更快一些.
  • 它保存了某个时间点得数据集,非常适用于数据集的备份
  • 会导致Redis在一些毫秒级内不能响应客户端的请求

    AOF:.aof文件

        配置文件:

  1. # 是否开启AOF,默认关闭(no)  
  2. appendonly yes  
  3.   
  4. # 指定 AOF 文件名  
  5. appendfilename appendonly.aof  
  6.   
  7. # Redis支持三种不同的刷写模式:  
  8. # appendfsync always #每次收到写命令就立即强制写入磁盘,是最有保证的完全的持久化,但速度也是最慢的,一般不推荐使用。  
  9. appendfsync everysec #每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,是受推荐的方式。  
  10. # appendfsync no 
  • AOF文件是一个只进行追加的日志文件,所以不需要写入seek,即使由于某些原因(磁盘空间已满,写的过程中宕机等等)未执行完整的写入命令,你也也可使用redis-check-aof工具修复这些问题.
  • Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写
  • 如果你不小心执行了 FLUSHALL 命令, 但只要 AOF 文件未被重写, 那么只要停止服务器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重启 Redis , 就可以将数据集恢复到 FLUSHALL 执行之前的状态。
  • AOF 文件的体积通常要大于 RDB 文件的体积

在运行情况下, Redis 以数据结构的形式将数据维持在内存中, 为了让这些数据在 Redis 重启之后仍然可用, Redis 分别提供了 RDB 和 AOF 两种持久化模式。

在 Redis 运行时, RDB 程序将当前内存中的数据库快照保存到磁盘文件中, 在 Redis 重启动时, RDB 程序可以通过载入 RDB 文件来还原数据库的状态。

RDB 功能最核心的是 rdbSave 和 rdbLoad 两个函数, 前者用于生成 RDB 文件到磁盘, 而后者则用于将 RDB 文件中的数据重新载入到内存中:

digraph persistent {    rankdir = LR;    node [shape = circle, style = filled];    edge [style = bold];    redis_object [label = "内存中的\n数据对象", fillcolor = "#A8E270"];    rdb [label = "磁盘中的\nRDB文件", fillcolor = "#95BBE3"];    redis_object -> rdb [label = "rdbSave"];    rdb -> redis_object [label = "rdbLoad"];}


rdbSave 函数负责将内存中的数据库数据以 RDB 格式保存到磁盘中, 如果 RDB 文件已存在, 那么新的 RDB 文件将替换已有的 RDB 文件。

在保存 RDB 文件期间, 主进程会被阻塞, 直到保存完成为止。

SAVE 和 BGSAVE 两个命令都会调用 rdbSave 函数,但它们调用的方式各有不同:

  • SAVE 直接调用 rdbSave ,阻塞 Redis 主进程,直到保存完成为止。在主进程阻塞期间,服务器不能处理客户端的任何请求。
  • BGSAVE 则 fork 出一个子进程,子进程负责调用 rdbSave ,并在保存完成之后向主进程发送信号,通知保存已完成。因为 rdbSave 在子进程被调用,所以 Redis 服务器在 BGSAVE 执行期间仍然可以继续处理客户端的请求。

关于SAVE 、BGSAVE和BGREWRITEAOF执行区别:

  • rdbSave 会将数据库数据保存到 RDB 文件,并在保存完成之前阻塞调用者。

  • SAVE 命令直接调用 rdbSave ,阻塞 Redis 主进程; BGSAVE 用子进程调用 rdbSave ,主进程仍可继续处理命令请求。

  • SAVE 执行期间, AOF 写入可以在后台线程进行, BGREWRITEAOF 可以在子进程进行,所以这三种操作可以同时进行。

  • 为了避免产生竞争条件, BGSAVE 执行时, SAVE 命令不能执行。

  • 为了避免性能问题, BGSAVE 和 BGREWRITEAOF 不能同时执行。

  • 调用 rdbLoad 函数载入 RDB 文件时,不能进行任何和数据库相关的操作,不过订阅与发布方面的命令可以正常执行,因为它们和数据库不相关联。发布与订阅功能和其他数据库功能是完全隔离的,前者不写入也不读取数据库,所以在服务器载入期间,订阅与发布功能仍然可以正常使用,而不必担心对载入数据的完整性产生影响。

BGSAVE

在执行 SAVE 命令之前, 服务器会检查 BGSAVE 是否正在执行当中, 如果是的话, 服务器就不调用 rdbSave , 而是向客户端返回一个出错信息, 告知在 BGSAVE 执行期间, 不能执行 SAVE 。

这样做可以避免 SAVE 和 BGSAVE 调用的两个 rdbSave 交叉执行, 造成竞争条件。

另一方面, 当 BGSAVE 正在执行时, 调用新 BGSAVE 命令的客户端会收到一个出错信息, 告知 BGSAVE 已经在执行当中。

BGREWRITEAOF 和 BGSAVE 不能同时执行:

  • 如果 BGSAVE 正在执行,那么 BGREWRITEAOF 的重写请求会被延迟到 BGSAVE 执行完毕之后进行,执行 BGREWRITEAOF 命令的客户端会收到请求被延迟的回复。
  • 如果 BGREWRITEAOF 正在执行,那么调用 BGSAVE 的客户端将收到出错信息,表示这两个命令不能同时执行。

BGREWRITEAOF 和 BGSAVE 两个命令在操作方面并没有什么冲突的地方, 不能同时执行它们只是一个性能方面的考虑: 并发出两个子进程, 并且两个子进程都同时进行大量的磁盘写入操作, 这怎么想都不会是一个好主意。





下面特意写出来,自己看了原文后的困惑

原文:

SAVE

前面提到过, 当 SAVE 执行时, Redis 服务器是阻塞的, 所以当 SAVE 正在执行时, 新的 SAVE 、 BGSAVE 或 BGREWRITEAOF 调用都不会产生任何作用。

只有在上一个 SAVE 执行完毕、 Redis 重新开始接受请求之后, 新的 SAVE 、 BGSAVE 或 BGREWRITEAOF 命令才会被处理。

另外, 因为 AOF 写入由后台线程完成, 而 BGREWRITEAOF 则由子进程完成, 所以在 SAVE 执行的过程中, AOF 写入和 BGREWRITEAOF 可以同时进行。

我的困惑:

save在执行时,服务器时阻塞的,为什么还能执行AOF的写入和BGREWRITEAOF呢?希望看到这篇文章的人,能回答下我的问题?


猜你喜欢

转载自blog.csdn.net/qq_33182756/article/details/80641025
今日推荐