[toc]
redis持久化是做什么的?就是为了做备份, 避免redis重启后要重新从数据库里拿缓存。
redis当前有两种持久化机制: RDB和AOC
RDB(Redis DataBase) redis快照#
Q: RDB有哪两种触发方式?#
A:
-
手动触发。 调用save或者bgsave命令进行快照和备份。
也可以配置redis.conf,做一个周期性快照,但本质上是使用上面这2个命令
-
自动触发。m秒内有n次修改,或者主从复制时会触发。
Q: save命令和bgsave命令有什么区别?#
A:
-
save命令会阻塞当前redis线程,导致缓存暂时不可用(stopwolrd), 只能在开发环境或者测试环境使用。
-
bgsave 会fork创建一个子进程,在子进程中做RDB操作。
RDB快照存盘完成后,会通知主进程,主进程更新统计信息。
Q: 如果一次执行好几个bgsave命令会怎么样?#
A:
当检测到有子进程时, 后面几个bgsave命令会直接返回,不会做创建。
Q: bgsave的过程中,如果主进程收到新的写数据怎么办?#
A:
主进程会把写数据生成一个副本,交给bgsave子进程, 子进程会把这个修改作为最新修改写入RDB文件。
Q: 这个同步副本给子进程的时候进程崩溃怎么办?导致没有落盘到RDB#
A:
RDB完全写入成功,才算成功。
写一半的RDB文件,被认为无效文件,因此会用上一次的有效RDB文件进行恢复。
Q: 每秒做一次bgsave会有什么问题?如果数据量比较大的话#
A:
- 磁盘压力比较大,频繁竞争磁盘通过(注意每次快照的文件都是不同的文件,但磁盘写入器会共用)
- 创建fork子线程的操作,本身会阻塞一定的主进程时间。
Q: 如何解决上面的问题, 又能尽可能保证备份的实时可靠性?#
A:
做增量快照(只备份新增的修改),而增量快照的话RDB无法支持。
Q: RDB的优缺点?#
A:
优点:
-
使用了LZF算法做了压缩,数据量小于内存大小,很适合备份、全量复制。
-
备份恢复速度比AOF快。
缺点:
-
效率不高,如果数据量太大的话。
-
fork子进程操作比较重
-
文件属于二进制文件,可读性差。
AOF(append only file)持久化方式#
Q: AOF采用 ”先更新内存缓存, 再写备份日志“, 和”mysql日志先行“的思想不同,为什么?#
A:
-
错误命令得调用redisobject方法的时候才能感知,写日志时不方便做检查。
如果写了错误命令的日志,再执行命令,就不好恢复了(那mysql为什么没有这个顾虑?)
-
尽快加速写操作的响应
风险就是正巧写的时候挂了,那日志也丢了。
Q: AOF记录时的3个步骤是怎样的?#
A:
-
命令追加
把写命令写道aof_buf缓冲区
-
文件写入和同步
什么时候写入文件,有3种策略
- always:每次写入缓冲区后,都马上写入文件
- everySec:每秒把缓冲区里的数据写一次到文件(可能丢失1秒)
- no:由操作系统控制合何时写文件
Q: 随着写入操作越来越多, AOF文件会越来越大,怎么办?#
A:
当大到一定成都时, redis会创建一个新的AOF文件, 对老文件里的命令进行重写,去除一些冗余命令,只保留每个键的最后状态。
重写操作也是fork了一个子线程进行重写
Q: 重写时,由新的数据写入怎么办?#
A:
同步2份写操作, 老AOF文件写一份, 新AOF文件的缓冲区同步一份。
-
主线程fork出子进程重写aof日志
-
子进程重写日志完成后,主线程追加aof日志缓冲
-
替换日志文件
Q: 如果重写的时候 redis重启了怎么办?#
A:
没写完的AOF文件默认失效, 使用老的AOF文件。
Q: 主进程如何拷贝数据给子进程?#
A:
使用操作系统的copy on write
子进程时会拷贝父进程的页表,即虚实映射关系(虚拟内存和物理内存的映射索引表),而不会拷贝物理内存
一般都采用RDB和AOF混合的方式, 先全量快照, 然后一段时间内增量AOF。
Q: 恢复时, 如果同时有RDB文件和AOF文件,怎么选择?#
A:
优先选择AOF文件,AOF不存在再RDB。
Q: 那么为什么会优先加载AOF呢?#
A:
因为AOF保存的数据更完整,通过上面的分析我们知道AOF基本上最多损失1s的数据。
Q: 线上高压环境如何进行备份机制的调优,减少阻塞?#
A:
- 关闭非敏感、重要性数据的备份
- 通过一些其他补数据机制进行恢复,例如自己写一些缓存重新载入的补数据功能。
- redis集群实现滚动备份,避免全部同时在备份。
- redis主从复制时, 让从节点做备份,主节点不做部分。