Redis数据持久化
Redis数据持久化
RDB快照(snapshot)
默认情况下,Redis会将内存数据库快照保存在一个名称为 dump.rdb 的二进制文件中。我们可以通过 .conf 配置文件中的 save 属性进行设置,让它在"N秒内数据集至少有M个改动"这一条件被满足时,自动保存一次数据。
当我们需要关闭RDB只需要将所有的save保存策略注释掉即可:
# ./redis.conf
# save 3600 1
# save 300 100
# save 60 10000
不仅如此,还可以手动执行命令生成RDB快照。进入Redis客户端执行命令 save 或者 bgsave 就可以生成 dump.rdb 快照文件,每执行一次命令,就会重新生成一个当前Redis内存的快照,并覆盖原有的rdb快照文件内容。
save 写入是同步执行的,当我们的redis内存过大时,要将如此大的数据量快照写入rdb文件中,是很耗时的,会阻塞我们其他线程的执行。因此redis也提供了另一种写入策略bgsave。
bgsave:写时复制(COW机制)
Redis借助操作系统的写时复制技术(Copy-On-Write,COW),在生成快照的同时,依旧可以正常处理写命令。其原理时由主线程fork生成的bgsave子进程,可以共享主线程的所有内存数据。bgsave子进程运行后,开始读取主线程的内存数据,并把它写入rdb文件。此时如果主线程对这些数据也都是读操作,则主线程与bgsave子进程互不影响;如果主线程要修改某一块数据时,则会将这块数据复制一份生成改数据的副本,再由bgsave子进程写入rdb文件,在这个过程中主线程仍然可以直接修改原来的数据。
save与bgsave对比
命令 | I/O类型 | 是否阻塞其他命令 | 复杂度 | 优点 | 缺点 |
---|---|---|---|---|---|
save | 同步 | 是 | O(n) | 不回消耗额外内存 | 阻塞客户端命令 |
bgsave | 异步 | 否(在生成子进程执行调用fork函数时会短暂阻塞) | O(n) | 不阻塞客户端命令 | 需要fork子进程,消耗内存 |
⚠️注意:配置自动生成rdb文件后台使用的是bgsave方式
AOF (append-only file)
快照功能并不是非常耐久(durable)。如果redis因为某些原因而造成故障停机,那么服务器将丢失最近写入和还未保存到快照中的数据。从1.1版本开始,redis增加了一种完全耐久的持久化方式:AOF持久化,价格修改的每一条指令记录进文件appendonly.aof中(先写入os
cache,每隔一段时间fsync到磁盘)。
可以通过修改配置文件来打开AOF功能:
# ./redis.conf
appendoly yes
打开AOF功能后,每当redis执行一次改变数据集的命令时(比如SET),这个命令就会被追加到AOF文件的末尾。这样的话,当redis重新启动时,程序就可以通过重新执行AOF文件中的命令来达到重建数据集的目的。
可以通过以下三个配置,告知redis多久才将数据fsync到磁盘一次:
# ./redis.conf
# appendfsync always
appendfsync everysec
# appendfsync no
- appendfsync always :每次有新命令追加到AOF文件时就执行一次,非常慢,很安全。
- appendfsync everysec:每秒一次,足够快,并且故障时仅丢失1s的数据。(默认)
- appendfsync no:从不提交,将数据交给操作系统处理,速度很快,最不安全的选择。
AOF重写
当文件里存在太多没用指令,AOF会定期根据内存的最新数据生成aof文件,也可以执行命令 bgrewriteaof 手动进行重写。
⚠️注意:AOF重写redis会fork出一个子进程去执行,不会对redis正常命令处理有太多影响。
以下两个配置可以控制AOF重写频率:
# ./redis.conf
# 文件自上一次重写后文件大小增长了100%则再次触发重写
auto-aof-rewrite-percentage 100
# 文件至少达到64m才会自动重写,文件太小恢复速度本来就很快,重写的意义不大
auto-aof-rewrite-min-size 64mb
RDB 和 AOF 对比
命令 | RDB | AOF |
---|---|---|
启动优先级 | 低 | 高 |
体积 | 小 | 大 |
回复速度 | 快 | 慢 |
安全性 | 容易丢失 | 根据策略决定 |
在生产环境下,我们可以选择两者都开启,当redis启动时如果rdb文件与aof文件都存在时,优先选择aof文件进行数据恢复,因为aof相对安全一点。
混合持久化 (Redis 4.0)
重启redis时,通常不会使用RDB来恢复内存状态,因为会丢失大量的数据。通常会使用AOF日志重放,但是日志系性能对RDB来说要慢得多,因此在redis实例很大的情况下,启动需要花费很长的时间。Redis
4.0为了结局这个问题,带来一种新的持久化 - 混合持久化。
# ./redis.conf
# 开启混合持久化
aof-use-rdb-preamble yes
当开启了混合持久化,AOF在重写时,不再是单纯将内存数据转换为RESP命令写入AOF文件,而是将重写这一刻之前的内存做RDB快照处理,并且将RDB快照内容和增量的AOF修改内存的命令存放在一起,都写入到新的AOF文件,新的文件一开始不叫 appendonly.aof ,等到重写完新的AOF文件才会进行改名,覆盖原有的AOF文件,完成新旧两个AOF文件的替换。于是在redis重启时,可以先加载RDB的内容,然后再放增量AOF日志就可以完全替代之前的AOF全量文件重放,因此重启效率会大幅提高。
⚠️注意:开启混合持久化,必须先开启AOF
Redis备份参考策略
- 写crontap定时调度脚本,每小时都copy一份rdb或aof到一个目录中去,仅仅保留最近48小时的备份;
- 每天都保留一份当日的数据备份到一个目录中去,可以保留最近一个月的备份;
- 每次copy备份的时候,把太久的备份删除;
- 每天晚上将当前机器上的备份复制一份到其他机器上,以防机器损坏数据丢失;