Redis 持久化机制:RDB和AOF

413 阅读4分钟

概述

大多数时候,我们使用Redis都是作为缓存使用,数据都是保存在内存中,一旦Redis退出/重启,原先服务器中的数据就丢失了,为了解决这个问题,Redis提供了两种持久化机制:RDBAOF,下面分别介绍这两种机制

RDB 持久化方案介绍

RDBRedis Database,是Redis的默认持久化方案,该方案会定期的将Redis中的数据写入到磁盘,生成一个当前时刻的快照文件,我们称其为RDB文件。当Redis服务意外重启时,会读取最新的RDB文件,使用该文件恢复服务器中的数据

RDB 工作原理

Redis服务端在接收到savebgsave时,会触发快照,生成RDB文件。以save为例,当执行save

127.0.0.1:6379> save 
OK

会在工作目录下生成dump.rdb文件

$ ls -al
total 8
drwxr-xr-x@ 3 huangxy  staff   96  3  7 18:00 .
drwxr-xr-x  4 huangxy  staff  128  3  3 22:45 ..
-rw-r--r--  1 huangxy  staff  188  3  7 18:00 dump.rdb

bgsave命令作用与save命令相同,唯一的区别是bgsave不会阻塞Redis服务端进程。所以实际工作中常用bgsave而不用save命令。当执行bgsave命令时,Redis会执行以下步骤:

  • forks一个子进程,用于持久化数据
  • 子进程开始将Redis中的数据写入到一个临时RDB文件中
  • 当子进程完成数据的写入操作后,使用当前的RDB文件替换之前旧的RDB文件

该工作流程类似于Copy-On-Write机制

RDB 配置

RDB文件默认保存在当前工作目录下的dump.rdb文件中,可以在redis.conf文件中配置文件的存放路径与文件名

# 配置 Redis 工作目录
dir ./
# 指定 RDB 文件名
dbfilename dump.rdb

除了手动执行bgsave命令生成RDB文件外,还可以在配置文件中设置save的规则,当满足规则时,服务器会自动执行bgsave操作

save 900 1
save 300 10
save 60 10000

save命令的格式为:save <seconds> <changes>,表示在seconds秒内,至少有changes次数据变化,就执行bgsave命令
save 900 1表示当15分钟内至少有1次数据改变,就执行bgsave,想要配置多个规则,可以多写几行save配置,当满足其中一条规则,就会执行bgsave命令

AOF 持久化方案介绍

RDB不同,AOF持久化会把服务器执行的写命令追加到AOF文件中。所以AOF文件中存放的就是具体的写命令,比如执行set操作

127.0.0.1:6379> set foo bar
OK

AOF文件中的内容如下

*3
$3
set
$3
foo
$3
bar

熟悉RESP协议的应该知道,该文件内容表示的就是set foo bar 当服务重启时,会重放AOF文件,执行AOF文件中的命令对数据进行恢复

AOF 配置

Redis默认不开启AOF持久化,可以在配置文件中添加下面配置打开AOF持久化功能

appendonly yes

开启AOF持久化后,为确保服务性能,执行写命令的时候,不是立即将命令写入到AOF文件中,而是先将命令写入到aof_buf缓存中,当满足一定条件时,再将缓存刷新到AOF文件中。对于aof_buf的刷新时机,Redis提供了下面三种策略

  • appendfsync always:每个写命令同步写入到AOF文件中,该策略数据安全性最高,但会对磁盘进行大量的写操作,Redis处理命令的速度会受到磁盘性能的影响
  • appendfsync everysec: 每秒同步一次aof_buf缓存到AOF文件中,使用该策略,即使服务器宕机,也只会丢失 1s 内的数据
  • appendfsync no: 不指定aof_buf文件的刷新时机,什么时候将aof_buf缓存中的数据写入到AOF文件中,由操作系统调度,该方案对Redis性能影响比较小,但当服务器宕机,可能会丢失不定数量的数据,因为缓存何时刷新由操作系统调度,用户并不知情

appendfsync的默认配置为everysec,即每秒同步一次

appendfsync everysec

此外,AOF文件保存路径与文件名同样可以配置,默认保存在工作路径下的appendonly.aof

# 配置 Redis 工作目录
dir ./
# 配置 AOF 文件名
appendfilename appendonly.aof

AOF 重写机制

随着命令不断写入AOF文件中,AOF文件会越来越大,这回造成使用该AOF进行数据恢复的时间变长。为了解决这个问题,Redis引入了AOF重写机制,可以通过手动/自动触发AOF重写,进而压缩AOF文件的大小,使文件能够更快的被Redis加载
重写后的文件为什么可以变小?具体原因有:

  • 进程内已经超时的数据不再写入文件,比如过期 key
  • 旧的AOF文件含有无效命令,比如Redis前后执行了同一个key的插入与删除操作,先执行插入set foo bar,后执行删除操作del foo,那么,在重写的时候,这两条命令就属于无效命令,重写的时候无需将这两条命令写入文件
  • 多条命令可以合并为一条,节省空间。比如lpush list alpush list blpush list c这三条命令其实可以合并为lpush list a b c这一条命令
    AOF重写可以手动/自动触发,手动触发直接使用bgrewriteaof命令。自动触发会根据auto-aof-rewrite-min-sizeauto-aof-rewrite-percentage参数确定触发时机
  • auto-aof-rewrite-min-size表示运行重写时,AOF文件的最小体积,即小于该大小不会触发重写,默认为64M
  • auto-aof-rewrite-percentage 表示当前AOF文件空间与上一次重写后AOF文件空间的比值,当超过该比值才执行重写 所以自动触发重写的时机为: aof_current_size>auto-aof-rewrite-min- size&&(aof_current_size-aof_base_size)/aof_base_size>=auto-aof-rewrite- percentage

RDB 与 AOF 对比

  • RDB保存着某个时间点的数据快照,因此RDB文件非常适合备份。比如你可以每天备份一次数据库中的文件,并在需要的时候恢复某个时间点的数据
  • RDB数据恢复的时间要比AOF
  • AOF数据安全性更高,当服务器宕机时丢失的数据往往更少(取决于fsync策略)
  • AOF是一个只追加的日志文件,且内容是可读的,适合紧急误删恢复

如何选取持久化方案

  • Redis作为缓存使用时,一般不用开启持久化机制
  • 如果将Redis作为持久化数据库使用,可以同时开启RDBAOF持久化,定期执行bgsave做数据快照备份,使用AOF保证数据不丢失

参考

喜欢我的文章可以搜索huangxy关注我的公众号,也可以扫下放二维码关注