Redis支持RDB和AOF两种持久化机制,有效避免因进程退出造成的数据丢失问题。
1. RDB
RDB持久化是把当前进程数据生成快照保存到硬盘的过程,触发过程分为手动触发和自动触发。
1.1 触发机制
- save命令:阻塞当前Redis服务器,知道RDB过程完成
- bgsave命令:fork创建子进程来负责持久化过程
1.2 流程说明
1.3 RDB文件的处理
- 保存:在dir配置目录下
- 压缩:LZF算法进行压缩处理
1.4 优缺点
- 紧凑压缩的二进制文件,适合备份全量复制场景
- 加载恢复快
- 没办法做到实时持久化/秒级持久化,每次fork成本高
- 二进制格式特定,不兼容
2. AOF(append only file)
以独立日志的方式每次写命令,重启时再重新执行命令达到恢复数据的目的。解决了实时性。
2.1 使用AOF
2.2 命令写入
写入文本协议格式:兼容性,可读性
追加到缓冲区
2.3 文件同步
多重AOF缓冲区同步文件策略
Linux系统调用write和fsync:
- write操作会出发延迟写,linux在内核提供页缓冲区来提高IO性能,同步硬盘操作依赖于系统调度机制。同步之前如果系统故障,则缓冲区内数据丢失
- fsync针对单个文件操作,强制硬盘同步,fsync将阻塞知道写入硬盘完成后返回,保证了数据持久化
2.4 重写机制
AOF文件重写是吧Redis进程内的数据转化为写命令同步到新AOF文件的过程
(可以理解为当前所有数据搞成一个AOF文件)
- 进程内超时数据不再写入
- 旧的AOF文件含有无效命令
- 多条写命令可以合并为一个
注意上图中,子进程生成新AOF文件的时候,父进程还在响应命令,这部分命令要放到aof_rewrite_buf缓冲区,最后合并到新的AOF文件。
2.5 重启加载
流程:开启AOF时,优先加载AOF
2.6 文件校验
加载损坏的AOF文件会拒绝启动,万一结尾不完整(掉电),也可以兼容一下,只会警告。
3. 问题定位与优化
持久化功能很容易影响性能
3.1 fork操作
fork操作耗时问题对线上应用延迟影响明显
3.2 子进程开销监控和优化
- CPU
- 内存
- 硬盘开销分析优化
优化思路:避免和其他竞争资源的服务一起部署
3.3 AOF追加阻塞
Redis使用另一条线程每秒执行fsync同步硬盘,当硬盘繁忙时,会造成主线程阻塞。所以不能每次操作都fsync确认,而是两秒一次。
4. 多实例部署
Redis是单线程架构,所以会在一台机器上部署多个Redis实例,都开启AOF重写会产生对CPU和IO的竞争。
所以通过外部程序轮询控制AOF重写操作的执行。
- 外部程序监控机器上所有Redis实例
- 对于开启AOF的实例,查看确认增长率
- 增长率超过特定阈值时,手动触发当前实例重写
- 运行期间循环检查,直到AOF重写结束
- 确认实例AOF重写完成后,再检查其他实例并重复操作,保证机器内每个Redis实例AOF重写串行化执行