持久化,顾名思义,是将内存同步到磁盘的过程。
redis支持三种持久化机制
-
RDB持久化
-
AOF持久化
-
RDB与AOF混合模式
一、RDB持久化¶
1.1 简介¶
RDB是Redis中的一种持久化机制,用于将数据保存到硬盘上的二进制文件中。
redis有两种方式进行RDB持久化
-
手动触发
-
自动触发
1.2 rdb文件¶
保存
config set dir {newDir}
config set dbfilename {newFileName}
压缩
config set rdbcompression {yes|no}
校验
config set rdbchecksum {yes|no}
redis-check-dump #使用该工具检测RDB文件并获取对应的错误报告
rdb文件示意图
-
文件头
-
文件内容
-
文件尾

1.3 save与bgsave¶
save: 执行时会阻塞redis(之前讲过redis是一个循环,save执行1秒,所有命令全部阻塞1秒)
bgsave:Redis会在后台通过fork异步进行快照操作,执行RDB备份的是子进程,主进程还可以继续进行命令操作。 可以通过lastsave 命令获取最后一次成功执行快照的时间
1.3.1 自动触发配置¶
#表示900秒内有1个键改动,就会执行rdb
save 900 1
#表示300秒内有10个键改动,就会执行rdb
save 300 10
#表示60秒内有1万个键改动,就会执行rdb
save 60 10000
#redis通过LZF算法对RDB文件进行压缩,会消耗子进程的cpu资源(多核,物理核、逻辑核有区别),如果是单核就
会影响主进程
rbcbcompression yes
#redis默认使用CRC64的算法对RDB文件进行完整性校验
rdbchecksum yes
1.3.2 bgsave持久化流程¶
bgsave命令的运作流程

1.4 rdb恢复-方式及优势¶
1.方式
关闭Redis
- 先把备份的文件拷贝到工作目录下 cp dump2.rdb dump.rdb
启动Redis, 备份数据会直接加
2.优势
-
适合大规模的数据恢复
-
对数据完整性和一致性要求不高更适合使用
-
节省磁盘空间
-
恢复速度快
3.劣势
-
Fork的时候,内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑
-
虽然Redis在fork时使用了写时拷贝技术,但是如果数据庞大时还是比较消耗性能。
-
在备份周期在一定间隔时间做一次备份,所以如果Redis意外down掉的话,就会丢失最后一次快照后的所有修改。
4.禁用
永久禁止RDB:
save # 停止周期性触发
动态停止:
redis-cli config set save #save后给空值,表示禁用保存策略
二、AOF持久化¶
2.1 简介¶
以日志的形式将所有写操作追加到文件的末尾,使得数据在文件中呈现出与Redis内存中相同的状态。
- 记录写操作命令;
- AOF 会将过期时间由相对转成绝对时间;
AOF为什么直接采用文本协议格式?
-
文本协议具有很好的兼容性
-
文本协议具有可读性,方便直接修改和处理
aof文件的内容
- 客户端与服务器间使用RESP进行交互
例如set hello world这条命令,在AOF缓冲区会追加如下文本(格式化显示的结果):
#参数数量为3个
*3
#set参数字节数分别是3
$3
set
#hello参数字节数分别是5
$5
hello
#world参数字节数分别是5
55
world
2.2 aof配置¶
aof相关配置
appendonly=yes #开启aof
appendfilename=appendonly.aof #配置aof的文件名,默认文件名是appendonly.aof。
appendfsync={everysec|always|no} #aof日志刷盘策略
动态设置
config set appendonly {yes|no}
config set appendfilename {newFileName}
config set appendfsync {everysec|always|no}
2.3 aof持久化流程¶
AOF的工作流程操作:
-
命令写入 (append)
-
文件同步(sync)
-
文件重写(rewrite)
重启加载 (load)

2.3.1 aof重写¶
AOF文件重写是把Redis进程内的数据转化为写命令同步到新AOF文件的过程。目的是为了解决AOF文件体积过大的问题,以减少磁盘空间的占用和提高读取性能。而且更小的AOF文件可以更快地被Redis加载。
AOF重写触发方式
- 手动触发(直接调用bgrewriteaof命令)
- 自动触发(根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数确定自动触发时机)
aof重写相关配置
# aof重写期间,新进来的命令会暂存内存,等重写完了,会追加(如果出现宕机,重写启动到现在的数据会丢失)
no-appendfsync-on-rewrite=yes
aof重写条件,是原来aof的2倍,且最小文件是64mb
#当前aof文件大小超过上一次重写的aof文件的100%进行重写
auto-aof-rewrite-percentage=10
#重写AOF文件所需的最小文件大小为64mb
auto-aof-rewrite-min-size=64mb
2.3.2 aof重写流程¶

2.4 aof文件恢复¶
正常恢复
-
修改默认的appendonly no,改为yes
-
将有数据的aof文件复制一份保存到对应目录(查看目录:config get dir)
恢复:重启redis然后重新加载
异常恢复
修改默认的appendonly no,改为yes
-
如遇到AOF文件损坏,通过/usr/local/bin/redis-check-aof--fix appendonly.aof进行恢复
-
备份被写坏的AOF文件
-
恢复:重启redis,然后重新加载

三、RDB与AOF的对比¶
RDB持久化
二进制数据
RDB文件紧凑体积小
网络传输快
恢复速度快
无法做到实时
AOF持久化
实时性好,支持秒级持久化
恢复速度慢
对性能影响大
rdb与aof对过期key的处理
-
过期key对RDB和AOF没有任何影响
-
过期key持久化到rdb之前,会检查是否过期,过期的key不进入RDB文件
-
过期key持久化到aof
当key过期后,还没有被删除,此时进行执行aof持久化操作,该key是不会进入aof文件的,因为没有发生修改命令
当key过期后,在发生删除操作时,程序会向aof文件追加一条del命令(在将来的以aof文件恢复数据的时候该过期的键就会被删掉)
- RDB文件恢复时,数据载入数据库之前,会对key先进行过期检查,如果过期,不导入数据库(主库情况)
aof重写时,会先判断key是否过期,已过期的key不会重写到aof文件
四、持久化问题优化¶
1.fork操作
对于ops几万的redis实例,fork秒级影响整体业务延时
如何改善
- 支持fork的虚拟化技术,避免使用Xen或者物理
通过分片,降低每个redis实例的容量,控制在10gb以内,如果性能要求更高,继续降低
降低fork操作频率
2.CPU&内存优化
-
不要和其他CPU密集型服务部署在一起,造成CPU过度竞争
-
多实例部署,尽量保证同一时刻只有一个子进程执行重写
关闭THP
3.磁盘优化
-
高流量使用SSD持久化
-
分盘存储分摊IO压力(redis 10多个实例都需要AOF持久化)
AOF追加阻塞问题优化
定位:
(1)日志输出
Asynchronous AOF fsync is taking too long (disk is busy). Writing the AOF buffer without waiting for fsync to complete, this may slow down Redis
(2)info Persistence统计中, aof_delayed_fsync指标会累加
(3)磁盘io监控
优化:
- 优化系统硬盘负载