RDB和AOF特点:(Redis 持久化)
RDB:保存为dump.rdb 文件
save 60 1000
- RDB在保存RDB文件时父进程唯一需要做的就是fork出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的性能.
- 与AOF相比,在恢复大的数据集的时候,RDB方式会更快一些.
- 它保存了某个时间点得数据集,非常适用于数据集的备份
- 会导致Redis在一些毫秒级内不能响应客户端的请求
AOF:.aof文件
配置文件:
- # 是否开启AOF,默认关闭(no)
- appendonly yes
- # 指定 AOF 文件名
- appendfilename appendonly.aof
- # Redis支持三种不同的刷写模式:
- # appendfsync always #每次收到写命令就立即强制写入磁盘,是最有保证的完全的持久化,但速度也是最慢的,一般不推荐使用。
- appendfsync everysec #每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,是受推荐的方式。
- # 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 文件中的数据重新载入到内存中:
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 可以同时进行。