概述
大多数时候,我们使用Redis都是作为缓存使用,数据都是保存在内存中,一旦Redis退出/重启,原先服务器中的数据就丢失了,为了解决这个问题,Redis提供了两种持久化机制:RDB和AOF,下面分别介绍这两种机制
RDB 持久化方案介绍
RDB 即 Redis Database,是Redis的默认持久化方案,该方案会定期的将Redis中的数据写入到磁盘,生成一个当前时刻的快照文件,我们称其为RDB文件。当Redis服务意外重启时,会读取最新的RDB文件,使用该文件恢复服务器中的数据
RDB 工作原理
Redis服务端在接收到save或bgsave时,会触发快照,生成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 a、lpush list b、lpush list c这三条命令其实可以合并为lpush list a b c这一条命令
AOF重写可以手动/自动触发,手动触发直接使用bgrewriteaof命令。自动触发会根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数确定触发时机 auto-aof-rewrite-min-size表示运行重写时,AOF文件的最小体积,即小于该大小不会触发重写,默认为64Mauto-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作为持久化数据库使用,可以同时开启RDB与AOF持久化,定期执行bgsave做数据快照备份,使用AOF保证数据不丢失
参考
- Redis Persistence: redis.io/topics/pers…
- 《Redis 开发与运维》
喜欢我的文章可以搜索huangxy关注我的公众号,也可以扫下放二维码关注