文章目录
Redis 是一种内存数据库,也就是说 Redis 服务器在运行时,系统为其分配了一部分内存来存储数据,若 Redis 服务突然宕机,内存里的数据将会丢失。
为了应对这种情况,必须通过持久化的方式将数据从内存保存到磁盘。
Redis 数据持久化有两种方案:
- RDB 持久化(Redis DataBase)
- AOF 持久化(Append-Only File)
RDB 是指将内存中某个时间点的全量数据备份,存储到磁盘文件(dump.rdb),这个文件是一个二进制压缩的紧凑文件。
AOF 是指将 Redis 的写操作命令追加到磁盘日志文件(appendonly.aof),这个文件是文本文件。
Redis 4 开始支持 AOF + RDB 混合持久化的方式。它结合了两者的优点,可通过 aof-use-rdb-preamble
配置项开启混合持久化的功能。
RDB 持久化是按指定的时间间隔存储数据集的全量快照。
AOF 持久化会记录 Redis 服务器接收的每个写入操作,这些操作将在服务器启动时进行重放(replay),以重建原始数据。并且仅采用追加方式。当日志太大时,Redis 会在后台重写日志。
需要理解并重视 RDB 和 AOF 之间的优劣。
RDB 持久化
RDB 是指每隔一段时间将内存中的数据集快照存储到磁盘文件(dump.rdb),是 Redis 的默认持久化方案。
RDB 持久化的触发有三种方式:
- save 命令(不推荐使用)
- bgsave 命令
- 配置文件中的自动持久化生成 RDB 文件(常说的就是它)
在 redis.conf 配置文件中配置,会以一段时间内达到指定修改的次数为规则来触发快照操作,快照文件名为 dump.rdb。每当 Redis 服务重启时,会从该文件中把数据加载到内存中(前提是没有开启 AOF)。
RDB 持久化除了可以根据配置文件中的策略来触发外,还可以使用 save 和 bgsave 命令手动来触发。
这两个命令的区别在于 save 会阻塞服务器进程。在执行save命令的过程中,服务器不能处理任何请求。
但是 bgsave(background save,后台保存)命令会通过一个子进程在后台处理 RDB 持久化。
本质上 save 和 bgsave 调用的都是 rdbSave 函数,因此 Redis 不允许 save 和 bgsave 命令同时执行,这也是为了避免 RDB 文件数据出现不一致性的问题。
save 命令触发方式
save 命令将内存数据的镜像保存为 RDB 文件。由于 Redis 是以单线程方式执行命令,因此 save 命令执行期间会阻塞 Redis 服务进程,Redis 服务不再处理任何命令,直到 RDB 文件创建完成为止。
一般不建议直接使用 save 命令执行持久化。Redis 执行 save 命令时会阻塞其余客户端的命令。
bgsave 命令触发方式
bgsave 命令使用 CopyOnWrite 机制来执行写时的复制操作。fork 出一个子进程,来处理备份操作,子进程将内存中的最新数据依次写入临时文件,此时父进程依旧可以处理客户端的请求,当子进程执行完毕后再将该临时文件重命名为 dump.rdb(替换掉原来的 dump.rdb)。所以,无论 bgsave 命令是否执行成功,dump.rdb 都不会受影响,因此建议使用 bgsave 命令。
执行 bgsave 命令时,Redis 还能继续处理客户端的请求。
配置文件自动持久化
异步备份,后台自动触发 RDB 持久化的配置项。
# 定时自动持久化的规则
save 900 1 # 每隔900秒(15分钟),至少有1个key发生变化
save 300 10 # 每隔300秒(5分钟),至少有10个key发生变化
save 60 10000 # 每隔60秒(1分钟),至少有10000个key发生变化
# 默认值是 yes
# 启用 RDB 快照时,如果最近一次 bgsave 出错,Redis 将禁止写操作
# 这样,一旦持久化出错,我们就可以及时察觉(尽管这种方式有点暴力)
stop-writes-on-bgsave-error yes
三个中的任意一个持久化规则被满足,服务器就会自动执行 bgsave 命令,进行 RDB 持久化。
每次持久化完成后,服务器为实现自动持久化而设置的时间计数器和次数计数器就会清零。并重新开始计数,因此,多个规则的效果是不会叠加的。
配置文件中默认开启的三个自动持久化规则,我们可以进行修改。当然,也可新增规则。
save <seconds> <changes>
RDB 持久化的优缺点
优点
RDB 文件是 Redis 按时间点保存的紧凑数据文件,非常适合全量备份。假如我们需要保存近一个月内的快照,可以每天每小时将 RDB 文件归档一次。这样,在发生灾难时,就可以轻松把数据还原到在不同时间点备份的数据。
RDB 文件是一个二进制压缩的紧凑文件,对于灾难恢复非常有用。
RDB 持久化机制最大限度地提高了 Redis 的性能。因为 Redis 父进程为了持久化所做的唯一工作就是 fork 一个子进程,由子进程来进行持久化的具体操作,父进程不会执行类似于磁盘 I/O 的操作。
相比 AOF 而言,如果要恢复的数据量很大,RDB 文件更小,恢复数据的速度更快。
缺点
RDB 每次都是对数据进行全量备份,比较耗时。
很难保证数据的高一致性。因为 RDB 并不是实时对数据进行备份,而是每隔一段时间(触发规则后)才进行数据备份。如果 Redis 服务器宕机(断电)了,那么在最近一次 RDB 备份之后的数据就会丢失。
AOF 持久化
AOF(Append Only File)是以日志文件的方式追加记录每次的写命令,可以很好地解决数据持久化的实时性和一致性。系统重启时,可以重放(replay) AOF 文件中的命令来恢复数据。
AOF 会先把写操作追加在 AOF 缓冲区,然后根据对应策略写入硬盘。
AOF 的实现流程分为三个步骤:append → write → fsync。
首先,append 把命令追加到 AOF 缓冲区,然后 write 将缓冲区的内容写入程序缓冲区,最后 fsync 将程序缓冲区的内容写入文件。
当 AOF 持久化功能处于开启状态时,服务器每执行完一条写命令就会将命令追加写入 aof_buf 缓冲区。而在服务重启时,会把 AOF 文件加载到缓冲区。
AOF 持久化开关配置
AOF 持久化开关的相关配置,如下:
# 是否开启 AOF 持久化功能,默认值为否
appendonly no
# AOF 持久化的日志文件名称
appendfilename "appendonly.aof"
# AOF 持久化的策略,默认值是 everysec
# appendfsync always
appendfsync everysec
# appendfsync no
fsync 是指告诉 OS 将缓冲区的数据写入磁盘,而不是等待缓冲区里有更多的数据。
appendfsync 选项的三个值的说明如下:
- no:不执行 fsync,让系统自己决定何时将缓冲区的数据,写入日志文件。视同只配置了 RDB 快照备份。安全性低,性能高。
- always:每次发生写操作,就立即执行 fsync,将数据写入日志文件。安全性高,性能低。
- everysec:每秒钟执行一次 fsync,将数据写入日志文件。安全性较高,性能较高。
三种策略中,everysec 是一种兼顾安全性和性能的折衷策略。如果有突发事件(服务器断电了),可能会丢失仅仅 1 秒内的数据。这是可以接受的。
如果你不确定选择哪一种策略,官方推荐采用 everysec。
AOF 日志文件重写规则配置
如果启用了 AOF 持久化功能,Redis 会以 append 的方式,不断将客户端的写命令追加到 AOF 日志文件,随着时间的推移,日志文件会变得越来越大。
当 AOF 日志文件的大小达到指定的阈值,Redis 会隐式调用 bgrewriteaof,自动对 AOF 文件进行重写。重写可以减少 AOF 文件的大小。
重写指的是将同一个 key 的多个命令的操作结果,合并为一个命令。
假如,原来的 AOF 文件内容为:
incr counter
incr counter
incr counter
set name jack
set name jack2
重写后的 AOF 文件内容为:
set counter 3
set name jack2
AOF 日志文件自动重写的配置项,默认如下:
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
意思是当 aof 文件的大小相比最近一次重写(若自服务启动后没有重写,就以启动时的文件大小为准)时增长 100%,且当前大小超过 64 mb 时,才触发重写。
AOF 持久化的优缺点
优点
AOF 持久化可以保证更好的数据安全性(完整性、一致性)。对于默认的 appendfsync everysec
配置,就算出现宕机,顶多也就可能丢失 1 秒内的数据。
AOF 采用的是 append 追加模式,相当于增量备份,和 RDB 的全量备份相比,备份速度更快。
在写入过程中即使出现宕机,也不会破坏 AOF 日志文件中已经存在的内容。如果由于某种原因(磁盘已满)导致日志只记录了一半,在 Redis 下一次启动前,可以利用 redis-check-aof 工具轻松修复。
AOF 文件自动重写机制,可以有效减少文件的大小。
AOF 文件是一个格式清晰、便于理解的日志文件,它记录了所有的写操作。
缺点
未经压缩,占用空间更多,对于相同的数据集,AOF 文件通常要大于 RDB 文件。
对于大数据量的恢复,AOF 比 RDB 慢很多。
一般而言,Redis 的数据持久化只采用 RDB 就够了。如果再同时开启 AOF,多少会牺牲一些系统的性能。
RDB 和 AOF 的对比
- 数据恢复优先级:AOF 高于 RDB。当 Redis 重启时,会先判断是否开启了 AOF,如果是,就使用 AOF 文件恢复数据;否则,使用 RDB 文件恢复数据。
- 文件大小:AOF 文件大于 RDB 文件。
- 恢复速度;AOF 文件比 RDB 文件慢。
- 安全性 & 实时性:一般而言,AOF 在安全性和实时性上更优;RDB 容易丢失数据。
RDB 和 AOF 各有优劣,对于 Redis 数据持久化的方案,该如何抉择?
- 一般而言,在生产环境中,最好同时使用 RDB 和 AOF。
- 如果你更在意 Redis 服务器的性能,可以忍受几分钟内的数据丢失,那么,你可以选择只使用 RDB。
- 由于 RDB 可以定时生成数据库全量快照,体积更小,数据恢复速度更快,非常适合数据库备份和灾难恢复。因此,不推荐只使用 AOF。
AOF + RDB 混合模式
从 Redis 4 开始,新增了 AOF + RDB 混合模式。
开启 AOF + RDB 混合模式后,当重写 AOF 文件时,会在 AOF 文件中,以 RDB 格式写入当前最新的数据,之后的写操作继续以 AOF 的追加形式记录写命令到 AOF 文件。
也就是说,重写后的 AOF 文件由两部分组成:
- 前面的部分是类似 RDB 文件的二进制快照
- 后面的部分是新追加的命令文本
当 Redis 重启时,会先加载 AOF 文件中前面的 RDB 部分,再加载剩余的 AOF 部分。
这样,就完美地融合了 AOF 和 RDB 持久化的优势。
AOF + RDB 混合模式持久化的配置如下:
# AOF + RDB 混合模式持久化,默认是开启的
aof-use-rdb-preamble yes
注意:前提是 AOF 和 RDB 各自都要开启。
127.0.0.1:6379> config get save
1) "save"
2) "900 1 300 10 60 10000"
127.0.0.1:6379> config get append*
1) "appendfsync"
2) "everysec"
3) "appendonly"
4) "yes"