AOF

AOF 日志格式

  • AOF 日志里面记录的是 Redis 接收到的每条命令
  • AOF 日志格式:
    • “*3"表示当前命令有三个部分
    • “$数字”:表示表示这部分中的命令、键、值一共有多少字节
    • set/key1/value1:具体的命令、键、值
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
*3
$3
set
$4
key1
$6
value1
*3
$3
set
$4
key2
$6
value2

写回策略

  • Always:同步写回,每个写命令执行完后,都会执行 fsync()
    • 可以保重数据不丢失,但是每次落盘操作都由主线程执行,可能会堵塞下一条命令的执行
  • Everysec:每秒写回,每个写命令执行完后,并不会直接落盘,而是写入操作系统的写buffer中,每秒执行 fsycn()
    • 减少了每次写操作都刷盘的压力,但是系统宕机会丢失上一秒的数据
  • No:由操作系统控制写回,Redis 将日志写入系统的写buffer中,由操作系统决定什么时候写入磁盘
    • 性能比较好,但是宕机时会丢失比较多的数据

AOF 重写

概述

  • 随着数据变更的增多,AOF 日志会不断增大,Redis 启动时加载数据所需的时间也会增加
  • 大量对于一个 key 的多次变更操作,导致一个 key 在日志中存储多分数据
  • AOF 重写相当于压缩掉中间 key 的变更、只保留 key 的终态结果
  • 重写机制最后会记录 set testkey testvalue 这样的命令。这样,在恢复时,可以重新执行该命令,实现 “testkey”: “testvalue” 的写入

执行方式(BGREWRITEAOF)

  • 每次执行重写时,主线程 fork 出后台的 bgrewriteaof 子进程。此时,fork 会把主线程的fork(Copy On Write)拷贝一份给 bgrewriteaof 子进程,这里面就包含了数据库的最新数据。
  • 然后,bgrewriteaof 子进程就可以在不影响主线程的情况下,逐一把拷贝的数据写成操作,记入重写日志。
  • 执行期间内的 AOF 日志,仍会写入新旧两个 AOF 文件的缓冲区
    • 写入旧 AOF 日志文件 用于防止这段期间内异常宕机引起的数据丢失
    • 写入新 AOF 日志文件 用于保证数据一致

RDB

RDB 格式

  • RDB 的持久化方式就类似于 内存快照,相当于把内存中的所有数据保存到磁盘中
  • RDB 记录的是某一时刻的数据,并不是操作,所以,在做数据恢复时,我们可以直接把 RDB 文件读入内存,很快地完成恢复

执行方式(BGSAVE/SAVE)

  • SAVE:在主线程中执行,会导致阻塞;
  • BASAVE:建一个子进程,专门用于写入 RDB 文件,避免了主线程的阻塞
    • 子进程会 fork 一份内存地址、采用 Copy On Write 的方式拷贝数据 需保证内存充足,极限情况下(bgsave 期间 Redis 中所有数据均发生变更)会完全复制一份内存,redis 内存大小会变为之前的两倍

AOF RDB 混写

  • 内存快照以一定的频率执行,在两次快照之间,使用 AOF 日志记录这期间的所有命令操作
  • 实际上还是以 AOF 的持久化配置调用,但是 AOF 重写时,并不是写 set key value 的方式,而是用 RDB 的方式写在 AOF 重写文件的头部,后续变更仍以 AOF 方式追加。

配置文件

AOF

  • appendonly:no/yes 默认为 no,是否开启 AOF
  • appendfilename “appendonly.aof”:持久化文件的名称
  • appendfsync always/everysec/no:AOF 落盘策略
  • no-appendfsync-on-rewrite no/yes:落盘时机为 everysec 或 always 时,后台如果有正在重写文件(包括bgsave、bgrewriteaof、bgrewriteaof)时,推迟 fsync() 的调用
  • auto-aof-rewrite-percentage:Redis能够在AOF文件大小增长了指定百分比时,自动隐式调用 BGREWRITEAOF 命令进行重写
    • 计算方法:当前AOF文件大小和上一次重写后AOF文件大小的差值,再除以上一次重写后AOF文件大小。也就是当前AOF文件比上一次重写后AOF文件的增量大小,和上一次重写后AOF文件大小的比值。
    • Redis记录上一次执行AOF重写后的文件大小作为基准。(如果启动后没有发生过重写,则使用启动时的AOF文件大小)。
    • 将该基准值与当前文件大小进行比较,如果当前体积超出基准值的指定百分比,将触发重写。
  • auto-aof-rewrite-min-size 64mb:AOF 日志小于 64mb 时,不触发 AOF 重写
  • aof-load-truncated:Redis 基于 AOF 日志恢复时,遇到文件末尾截断时,是继续加载文件还是报错退出
    • Redis所在的机器运行崩溃,就可能导致该现象
    • 当发生了末尾截断,Redis可以选择直接报错退出,或者继续执行并恢复尽量多的数据(默认选项)
    • yes :末尾被截断的 AOF 文件将会被加载,并打印日志通知用户。
    • no :服务器将报错并拒绝启动。(可使用 redis-check-aof 修复 AOF 文件)

RDB

  • save 3600 1:3600秒内,至少有1个key值改变,则落盘
    • save “":关闭 RDB 持久化方式
  • stop-writes-on-bgsave-error no/yes:默认为no,如果RDB文件写入过程中出错、Redis则认为持久化出现问题、会禁止所有的写入操作
  • rdbcompression yes:Redis 写 RDB 文件时,是否压缩
  • rdbchecksum:默认值是yes。在存储快照后,我们还可以让redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能。

AOF/RDB 混合落盘

  • aof-use-rdb-preamble yes/no:AOF 重写时,在文件头写入 RDB 文件,而不是类似于set kye value 的AOF文件,后续变更用AOF格式文件追加