Redis持久化原理 — RDB与AOF详细解释

一、持久化的作用

1. 什么是持久化

持久化(Persistence),即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。
持久化Redis所有数据保持在内存中,对数据的更新将异步地保存到磁盘上。

Redis持久化原理 — RDB与AOF详细解释

2. 持久化的实现方式

快照方式持久化

快照方式持久化就是在某时刻把所有数据进行完整备份。

例:Mysql的Dump方式、Redis的RDB方式。

写日志方式持久化

写日志方式持久化就是把用户执行的所有写指令(增删改)备份到文件中,还原数据时只需要把备份的所有指令重新执行一遍即可。

例:Mysql的Binlog、Redis的AOF、Hbase的HLog。

二、RDB

1. 什么是RDB

RDB简介

Redis持久化原理 — RDB与AOF详细解释

RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储。
在默认情况下, Redis 将数据库快照保存在名字为 dump.rdb的二进制文件中。
在 Redis 运行时, RDB 程序将当前内存中的数据库快照保存到磁盘文件中, 在 Redis 重启动时, RDB 程序可以通过载入 RDB 文件来还原数据库的状态。

工作方式

当 Redis 需要保存 dump.rdb 文件时, 服务器执行以下操作:

  1. Redis 调用forks。同时拥有父进程和子进程。
  2. 子进程将数据集写入到一个临时 RDB 文件中。
  3. 当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。

这种工作方式使得 Redis 可以从写时复制(copy-on-write)机制中获益。

2. RDB的三种主要触发机制

save命令(同步数据到磁盘上)

save 命令执行一个同步操作,以RDB文件的方式保存所有数据的快照。

127.0.0.1:6379> save
OK

Redis持久化原理 — RDB与AOF详细解释

由于 save 命令是同步命令,会占用Redis的主进程。若Redis数据非常多时,save命令执行速度会非常慢,阻塞所有客户端的请求。
因此很少在生产环境直接使用SAVE 命令,可以使用BGSAVE 命令代替。如果在BGSAVE命令的保存数据的子进程发生错误的时,用 SAVE命令保存最新的数据是最后的手段。

Redis持久化原理 — RDB与AOF详细解释

bgsave命令(异步保存数据到磁盘上)

bgsave 命令执行一个异步操作,以RDB文件的方式保存所有数据的快照。

127.0.0.1:6379> bgsave
Background saving started

Redis使用Linux系统的fock()生成一个子进程来将DB数据保存到磁盘,主进程继续提供服务以供客户端调用。
如果操作成功,可以通过客户端命令LASTSAVE来检查操作结果。

Redis持久化原理 — RDB与AOF详细解释

savebgsave 对比

命令 save bgsave
IO类型 同步 异步
阻塞? 是(阻塞发生在fock(),通常非常快)
复杂度 O(n) O(n)
优点 不会消耗额外的内存 不阻塞客户端命令
缺点 阻塞客户端命令 需要fock子进程,消耗内存

自动生成RDB

除了手动执行 savebgsave 命令实现RDB持久化以外,Redis还提供了自动自动生成RDB的方式。

你可以通过配置文件对 Redis 进行设置, 让它在“ N 秒内数据集至少有 M 个改动”这一条件被满足时, 自动进行数据集保存操作。
比如说, 以下设置会让 Redis 在满足“ 60 秒内有至少有 1000 个键被改动”这一条件时, 自动进行数据集保存操作:

save 60 1000

Redis持久化原理 — RDB与AOF详细解释

3. RDB相关配置

# RDB自动持久化规则
# 当 900 秒内有至少有 1 个键被改动时,自动进行数据集保存操作
save 900 1
# 当 300 秒内有至少有 10 个键被改动时,自动进行数据集保存操作
save 300 10
# 当 60 秒内有至少有 10000 个键被改动时,自动进行数据集保存操作
save 60 10000

# RDB持久化文件名
dbfilename dump-<port>.rdb

# 数据持久化文件存储目录
dir /var/lib/redis

# bgsave发生错误时是否停止写入,通常为yes
stop-writes-on-bgsave-error yes

# rdb文件是否使用压缩格式
rdbcompression yes

# 是否对rdb文件进行校验和检验,通常为yes
rdbchecksum yes

4. RDB的优点

  1. RDB是一个非常紧凑的文件,它保存了某个时间点得数据集,非常适用于数据集的备份,比如你可以在每个小时报保存一下过去24小时内的数据,同时每天保存过去30天的数据,这样即使出了问题你也可以根据需求恢复到不同版本的数据集。
  2. RDB是一个紧凑的单一文件,很方便传送到另一个远端数据中心或者亚马逊的S3(可能加密),非常适用于灾难恢复。
  3. RDB在保存RDB文件时父进程唯一需要做的就是fork出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的性能。
  4. 与AOF相比,在恢复大的数据集的时候,RDB方式会更快一些。

5. RDB的缺点

  1. 耗时、耗性能。RDB 需要经常fork子进程来保存数据集到硬盘上,当数据集比较大的时候,fork的过程是非常耗时的,可能会导致Redis在一些毫秒级内不能响应客户端的请求。如果数据集巨大并且CPU性能不是很好的情况下,这种情况会持续1秒,AOF也需要fork,但是你可以调节重写日志文件的频率来提高数据集的耐久度。
  2. 不可控、丢失数据。如果你希望在redis意外停止工作(例如电源中断)的情况下丢失的数据最少的话,那么RDB不适合你。虽然你可以配置不同的save时间点(例如每隔5分钟并且对数据集有100个写的操作),是Redis要完整的保存整个数据集是一个比较繁重的工作,你通常会每隔5分钟或者更久做一次完整的保存,万一在Redis意外宕机,你可能会丢失几分钟的数据。

三、AOF

1. 什么是AOF

快照功能(RDB)并不是非常耐久(durable): 如果 Redis 因为某些原因而造成故障停机, 那么服务器将丢失最近写入、且仍未保存到快照中的那些数据。 从 1.1 版本开始, Redis 增加了一种完全耐久的持久化方式: AOF 持久化。
你可以在配置文件中打开AOF方式:

appendonly yes

打开AOF后, 每当 Redis 执行一个改变数据集的命令时(比如 SET), 这个命令就会被追加到 AOF 文件的末尾。这样的话, 当 Redis 重新启时, 程序就可以通过重新执行 AOF 文件中的命令来达到重建数据集的目的。

AOF运行原理 - 创建

Redis持久化原理 — RDB与AOF详细解释

AOF运行原理 - 恢复

Redis持久化原理 — RDB与AOF详细解释

2. AOF持久化的三种策略

你可以通过配置文件配置 Redis 多久才将数据 fsync 到磁盘一次。

always

每次有新命令追加到 AOF 文件时就执行一次 fsync :非常慢,也非常安全。

Redis持久化原理 — RDB与AOF详细解释

everysec

每秒 fsync 一次:足够快(和使用 RDB 持久化差不多),并且在故障时只会丢失 1 秒钟的数据。
推荐(并且也是默认)的措施为每秒 fsync 一次, 这种 fsync 策略可以兼顾速度和安全性。

Redis持久化原理 — RDB与AOF详细解释

no

从不 fsync :将数据交给操作系统来处理,由操作系统来决定什么时候同步数据。更快,也更不安全的选择。

Redis持久化原理 — RDB与AOF详细解释

always、everysec、no对比

命令 优点 缺点
always 不丢失数据 IO开销大,一般SATA磁盘只有几百TPS
everysec 每秒进行与fsync,最多丢失1秒数据 可能丢失1秒数据
no 不用管 不可控

推荐(并且也是默认)的措施为每秒 fsync 一次, 这种 fsync 策略可以兼顾速度和安全性。

3. AOF重写

因为 AOF 的运作方式是不断地将命令追加到文件的末尾, 所以随着写入命令的不断增加, AOF 文件的体积也会变得越来越大。举个例子, 如果你对一个计数器调用了 100 次 INCR , 那么仅仅是为了保存这个计数器的当前值, AOF 文件就需要使用 100 条记录(entry)。然而在实际上, 只使用一条 SET 命令已经足以保存计数器的当前值了, 其余 99 条记录实际上都是多余的。
为了处理这种情况, Redis 支持一种有趣的特性: 可以在不打断服务客户端的情况下, 对 AOF 文件进行重建(rebuild)。执行 bgrewriteaof 命令, Redis 将生成一个新的 AOF 文件, 这个文件包含重建当前数据集所需的最少命令。
Redis 2.2 需要自己手动执行 bgrewriteaof 命令; Redis 2.4 则可以通过配置自动触发 AOF 重写。

Redis持久化原理 — RDB与AOF详细解释

AOF重写的作用

  • 减少磁盘占用量
  • 加速数据恢复

AOF重写的实现方式

  • bgrewriteaof 命令

    Redis bgrewriteaof 命令用于异步执行一个 AOF(AppendOnly File)文件重写操作。重写会创建一个当前AOF文件的体积优化版本。
    即使 bgrewriteaof 执行失败,也不会有任何数据丢失,因为旧的AOF文件在 bgrewriteaof 成功之前不会被修改。
    AOF 重写由 Redis 自行触发,bgrewriteaof 仅仅用于手动触发重写操作。
    具体内容:

    • 如果一个子Redis是通过磁盘快照创建的,AOF重写将会在RDB终止后才开始保存。这种情况下BGREWRITEAOF任然会返回OK状态码。从Redis 2.6起你可以通过INFO命令查看AOF重写执行情况。
    • 如果只在执行的AOF重写返回一个错误,AOF重写将会在稍后一点的时间重新调用。

Redis持久化原理 — RDB与AOF详细解释

  • AOF重写配置
配置名 含义
auto-aof-rewrite-min-size 触发AOF文件执行重写的最小尺寸
auto-aof-rewrite-percentage 触发AOF文件执行重写的增长率
统计名 含义
aof_current_size AOF文件当前尺寸(字节)
aof_base_size AOF文件上次启动和重写时的尺寸(字节)

AOF重写自动触发机制,需要同时满足下面两个条件:

  • aof_current_size > auto-aof-rewrite-min-size
  • (aof_current_size - aof_base_size) * 100 / aof_base_size > auto-aof-rewrite-percentage

假设 Redis 的配置项为:

auto-aof-rewrite-min-size 64mb
auto-aof-rewrite-percentage 100

当AOF文件的体积大于64Mb,并且AOF文件的体积比上一次重写之久的体积大了至少一倍(100%)时,Redis将执行 bgrewriteaof 命令进行重写。

AOF重写的流程

Redis持久化原理 — RDB与AOF详细解释

3. AOF相关配置

Redis持久化原理 — RDB与AOF详细解释

上一篇:sqoop导入数据到mysql原理_sqoop的详细使用及原理


下一篇:NocoDB 安装使用