Redis持久化 - RDB和AOF

1、持久化的做用

1. 什么是持久化

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

Redis持久化

2. 持久化的实现方式

快照方式持久化

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

例:Mysql的Dump方式、Redis的RDB方式。数据库

写日志方式持久化

写日志方式持久化就是把用户执行的全部写指令(增删改)备份到文件中,还原数据时只须要把备份的全部指令从新执行一遍便可。安全

例:Mysql的Binlog、Redis的AOF、Hbase的HLog。服务器

2、RDB

1. 什么是RDB

RDB简介

RDB持久化

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

工做方式

当 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

save命令

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

save命令阻塞全部客户端的请求

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

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

127.0.0.1:6379> bgsave
Background saving started

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

bgsave命令

savebgsave 对比

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

自动生成RDB

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

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

save 60 1000

自动生成RDB

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意外宕机,你可能会丢失几分钟的数据。

3、AOF

1. 什么是AOF

快照功能(RDB)并非很是耐久(durable): 若是 Redis 由于某些缘由而形成故障停机, 那么服务器将丢失最近写入、且仍未保存到快照中的那些数据。 从 1.1 版本开始, Redis 增长了一种彻底耐久的持久化方式: AOF 持久化。
你能够在配置文件中打开AOF方式:

appendonly yes

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

AOF运行原理 - 建立

建立AOF

AOF运行原理 - 恢复

AOF运行原理 - 恢复

2. AOF持久化的三种策略

你能够经过配置文件配置 Redis 多久才将数据 fsync 到磁盘一次。

always

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

always

everysec

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

everysec

no

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

no

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 重写。

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重写将会在稍后一点的时间从新调用。

bgrewriteaof命令

  • 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重写的流程

AOF重写的流程*

3. AOF相关配置

# 开启AOF持久化方式
appendonly yes

# AOF持久化文件名
appendfilename appendonly-<port>.aof

# 每秒把缓冲区的数据同步到磁盘
appendfsync everysec

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

# 是否在执行重写时不一样步数据到AOF文件
# 这里的 yes,就是执行重写时不一样步数据到AOF文件
no-appendfsync-on-rewrite yes

# 触发AOF文件执行重写的最小尺寸
auto-aof-rewrite-min-size 64mb

# 触发AOF文件执行重写的增加率
auto-aof-rewrite-percentage 100

4. AOF的优势

  1. 使用AOF 会让你的Redis更加耐久: 你可使用不一样的fsync策略:无fsync,每秒fsync,每次写的时候fsync。使用默认的每秒fsync策略,Redis的性能依然很好(fsync是由后台线程进行处理的,主线程会尽力处理客户端请求),一旦出现故障,你最多丢失1秒的数据。
  2. AOF文件是一个只进行追加的日志文件,因此不须要写入seek,即便因为某些缘由(磁盘空间已满,写的过程当中宕机等等)未执行完整的写入命令,你也也可以使用redis-check-aof工具修复这些问题。
  3. Redis 能够在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写: 重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。 整个重写操做是绝对安全的,由于 Redis 在建立新 AOF 文件的过程当中,会继续将命令追加到现有的 AOF 文件里面,即便重写过程当中发生停机,现有的 AOF 文件也不会丢失。 而一旦新 AOF 文件建立完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操做。
  4. AOF 文件有序地保存了对数据库执行的全部写入操做, 这些写入操做以 Redis 协议的格式保存, 所以 AOF 文件的内容很是容易被人读懂, 对文件进行分析(parse)也很轻松。 导出(export) AOF 文件也很是简单: 举个例子, 若是你不当心执行了 FLUSHALL 命令, 但只要 AOF 文件未被重写, 那么只要中止服务器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重启 Redis , 就能够将数据集恢复到 FLUSHALL 执行以前的状态。

5. AOF的缺点

  1. 对于相同的数据集来讲,AOF 文件的体积一般要大于 RDB 文件的体积。
  2. 根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。 在通常状况下, 每秒 fsync 的性能依然很是高, 而关闭 fsync 可让 AOF 的速度和 RDB 同样快, 即便在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 能够提供更有保证的最大延迟时间(latency)。

4、RDB和AOF的抉择

1. RDB 和 AOF 对比

- RDB AOF
启动优先级
体积
恢复速度
数据安全性 丢数据 根据策略决定

2. 如何选择使用哪一种持久化方式?

通常来讲, 若是想达到足以媲美 PostgreSQL 的数据安全性, 你应该同时使用两种持久化功能。

若是你很是关心你的数据, 但仍然能够承受数分钟之内的数据丢失, 那么你能够只使用 RDB 持久化。

有不少用户都只使用 AOF 持久化, 但并不推荐这种方式: 由于定时生成 RDB 快照(snapshot)很是便于进行数据库备份, 而且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快。