Appearance
Redis 持久化
1. Redis 持久化的意义
Redis 持久化的意义,在于故障恢复。
如果没有对数据进行持久化,那么如果 Redis 遇到灾难性的故障,就会丢失所有的数据。
如果通过 Redis 的持久化机制将数据持久化到硬盘上面去,然后在定期将磁盘上的文件备份到一起其他的服务器上面(比如:云服务器),这样就可以保证即使 Redis 遇到了灾难事故,也可以使用提前备份的文件对数据进行回复,之后丢失最近的一部分数据,而不会全部丢失数据。
2. Redis 的两种持久化方式
2.1. RDB、AOF 简介
Redis 的持久化是跟高可用相关的。Redis 有两种持久化的方式,分别是 RDB 和 AOF。
RDB 持久化机制,对 Redis 中的数据执行周期性的持久化。
AOF 机制对每条写入命令作为日志,以 append-only 的模式写入一个日志文件中,在 Redis 重启的时候,可以通过恢复 AOF 日志中的写入指令来重新构建整个数据集。
如果我们想要 Redis 仅仅作为纯内存的缓存来用,那么可以禁止 RDB 和 AOF 所有持久化机制。
通过 RDB 或 AOF,都可以将 Redis 内存中的数据给持久化到磁盘上面去,然后可以将这些数据备份到别的地方去。
如果 Redis 挂了,服务器上的内存和磁盘上的数据都丢了,可以从云服务上拷贝回来之前的数据,放到指定的目录中,然后重新启动 Redis,Redis 就会自动根据持久化数据文件中的数据,去恢复内存中的数据,继续对外提供服务。
2.2. RDB
2.2.1. RDB 底层原理
BGSAVE 时,Redis 会 Fork 主进程得到子进程,子进程共享主进程的内存数据。完成 Fork 后读取内存数据并写入 RDB 文件。父进程继续服务,通过写时复制(Copy-On-Write,COW)实现主线程不阻塞。
- Fork 瞬间:父子进程共享同一块物理内存(复制父进程的页表,但不复制物理页面);
- 写时复制:父进程继续接受写命令,只有当父进程修改某个页面时,内核才复制该页面给父进程,子进程仍然看到旧数据;
- 内存开销:最坏情况下,Fork 后所有页面都被写,内存翻倍。实际通常只有少量页面被改动。
2.2.2. RDB 优点
RDB 会生成多个数据文件,每个数据文件代表了某一个时刻中 Redis 的数据,这种多个数据文件的方式,非常适合做冷备。
做冷备优势:由 Redis 去控制固定时长生成快照文件的事情,比较方便;在最坏的情况下,提供数据恢复的时候,比 AOF 速度快。
RDB 持久化对 Redis 对外提供的读写服务,影响非常小,可以让 Redis 保持高性能,因为 Redis 主进程会 Fork 一个子进程,让子进程执行磁盘的 IO 操作来进行 RDB 持久化。
原因:RDB 直接写 Redis 内存,只是在一定时候,才会将数据写入内存。AOF 每次都是直接写文件,虽然可以快速的写 os cache 中,但还是要耗费一定时间,比 RDB 略慢一些。
相对于 AOF 持久化机制来说,直接基于 RDB 数据文件来重启和恢复 Redis 进程,更加快速。
原因:AOF,存放的指令日志,做数据恢复的时候,其实是要回放和执行所有的指令日志,来恢复出来内存中的所有数据的。
RDB,就是一份数据文件,恢复的时候,直接加载到内存中即可。
2.2.3. RDB 缺点
如果想要在 Redis 故障时,尽可能少的丢失数据,那么 RDB 没有 AOF 好。因为 RDB 都是每隔一段时间去做的备份,如果 Redis 宕机,那么就会丢失这一段时间内所有的数据。所以不适合做第一优先的恢复方案。
RDB 每次在 Fork 子进程来执行 RDB 快照文件生成的时候,如果数据文件特别大,可能会导致对客户端提供的服务暂停数毫秒,甚至数秒。
一般不要让 RDB 的间隔时间太长,否则每次生成的 RDB 文件太大了,对 Redis 本身的性能也有影响。
2.3. AOF
2.3.1. AOF 优点
AOF 可以更好的保护数据不丢失。
AOF 命令记录的频率(
appendfsync)可以通过 redis.conf 配置:配置值 刷盘时机 优点 缺点 always同步刷盘 可靠性高,几乎不丢数据 性能影响大 everysec每秒刷盘 性能适中 最多丢失 1 秒数据 no操作系统控制 性能最好 可靠性较差,可能丢失大量数据 AOF 日志文件是以 append-only 模式写入,所以没有任何的磁盘寻址的开销,写入性能非常高,而且文件不容易破损,即使文件意外破损,也很容易修复。
AOF 日志文件即使过大的时候,出现后台重写操作,也不会影响客户端的读写。
原因:因为在 rewrite log 的时候,会对其中的指令进行压缩,创建出一份恢复数据的最小日志出来。在创建新日志文件的时候,老的日志文件还是照常写入。当新的 merge 后的日志文件 ready 的时候,再交换新老日志文件即可。
AOF 日志文件的命令是通过非常可读的方式进行记录的,这非常适合做误删除这种操作的紧急恢复。
原因:比如某人不小心用 flushall 命令清空了所有数据,只要这个时候后台 rewrite 还没有发生,那么就可以立即拷贝 AOF 文件,将最后一条 flushall 命令给删了,然后再将该 AOF 文件放回去,就可以通过恢复机制,自动恢复所有数据。
2.3.2. AOF 缺点
对于同一份数据来说,AOF 日志通常比 RDB 文件更大。
AOF 开启后,支持的 QPS 会比 RDB 支持的 QPS 低。
原因:因为 AOF 一般会配置成每秒 fsync 一次日志文件,当然,每一秒 fsync 性能还是可以的。
AOF 比 RDB 更加脆弱,可能会出现恢复出来的数据不一致的情况。类似 AOF 这种较为复杂的基于命令日志/merge/回放的方式,比基于 RDB 每次持久化一份完整的数据快照文件的方式,更加脆弱一些,容易有 bug。不过 AOF 就是为了避免 rewrite 过程导致的 bug,因此每次 rewrite 并不是基于旧的指令日志进行 merge 的,而是基于当时内存中的数据进行指令的重新构建,这样健壮性会好很多。
在做数据恢复的时候比较慢,想用来做冷备、定期备份比较麻烦,可能要自己写脚本去做。不太适合做冷备。
3. RDB 和 AOF 如何选择
不要仅仅使用 RDB,这样会导致丢失很多数据。
也不要仅仅使用 AOF,因为使用 AOF 做冷备恢复速度太慢,还有可能会出现数据不一致。
综合使用 RDB 和 AOF 两种持久化机制,用 AOF 保证数据不丢失,作为数据恢复的第一选择;用 RDB 来做不同程度的冷备,在 AOF 文件都丢失或者不可以的时候,还可以用 RDB 来进行快速的数据恢复。