Redis持久化机制
redis支持RDB和AOF两种持久化机制,持久化功能有限地避免进程退出造成的数据丢失问题,当下次重启时利用之前持久化的文件即可是事先数据恢复。
1 RDB
RDB持久化是按照事先定制的策略,周期性的从内存中读取出来保存至硬盘,数据文件默认为dump.rdb;触发RDB持久化过程分为手动触发和自动触发;
1.1 触发机制
1)手动触发分别对应SAVE和BGSAVE命令;
-
SAVE命令:同步,在主线程中保存快照;此时会堵塞所有客户端请求;对于内存比较大的实例会造成长时间堵塞,线上环境不建议使用;
- BGSAVE命令:异步,Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。堵塞只发生在fork阶段,一般时间很短;
显然BGSAVE命令是针对SAVE堵塞问题做的优化。因此Redis内部所有的设计RDB的操作都采用BGSAVE的方式,而save命令已经废弃。
2)自动触发RDB的持久化机制,例如一下场景;
- 使用save相关配置,如“save m n”。表示m秒内数据采集存在n次修改时,自动触发bgsave。
- 如果从节点执行全量复制操作,主节点自动执行BGSAVE生成RDB文件并发送给从节点。
- 执行debug reload命令重新加载Redis时,也会自动触发save操作。
- 默认情况下执行shutdown命令时,如果没有开启AOF持久化功能则自动执行BGSAVE。
1.2 RDB相关配置
SAVE 900 1 #900秒内如果超过1个key被修改,则发起快照保存
SAVE 300 10 #300秒内容如超过10个key被修改,则发起快照保存
SAVE 60 10000 #60秒内容如果超过10000个key被修改,则发起快照保存
SAVE "" #关闭RDB功能
stop-writes-on-bgsave-error yes #在进行快照备份时,一旦监控到持久化发生错误,是否停止操作
rdbcompression yes #RDB文件是否执行压缩来节约空间
rdbchecksum yes #是否对RDB的镜像文件做校验码进行检测
dbfilename dump.rdb #指明快照文件名字
dir /data/redis/ #指明文件报错目录
1.3 流程说明
1)Redis调用系统函数fork(),创建一个子进程,fork操作过程中父进程会阻塞。
2)父进程继续处理各客户端发出的请求,当子进程将快照写入到临时RDB文件完成时。
3)Redis会用心的临时RDB文件替换原来的RDB文件,并删除旧RDB文件。
1.5 RDB的优缺点
RDB的优点:
- RDB是一个紧凑压缩的二进制文件,代表Redis在某个时间点上的数据快照。非常适用于备份,全量复制等场景。比如每6小时执行BGSAVE备份,并把RDB文件拷贝到远程机器或者文件系统中(如HDFS),用于灾难恢复。
- Redis加载RDB恢复数据远远快于AOF的方式。
RDB的缺点:
- RDB方式数据没办法做到持久化/秒级持久化。因为BGSAVE每次运行都要执行fork操作创建子进程,属于重量级操作,平凡执行成本过高。
- RDB文件使用特定二进制格式保存,Redis版本演进过程中有多个格式的RDB版本,存在老版本Redis服务无法兼容新版RDB格式的问题。
针对RDB不适合实时持久化的问题,Redis提供了AOF持久化方式来解决。
2 AOF
AOF持久化是把每一个命令的操作模式都记录下来,通过记录每一次写操作至指定的文件尾部实现持久化机制,当Redis重启时,可通过重新执行文件中的命令在内存中重建数据库,
2.1 使用AOF
开启AOF功能需要设置配置:appendonly yes,默认不开启。AOF文件名通过appendfilename配置设置,默认文件名是appendonly.aof。AOF的工作流程操作:命令写入(append)、文件同步(sync)、文件重新(rewrite)、重启加载(load)
2.2 AOF相关配置
appendonly yes #开启AOF功能 appendfilename "appendonly.aof" #启用的文件名字 appendfsync {always | everysec | no} {每次收到写命令就立即写入磁盘中的AOF文件|每秒钟写一次|自行不会触发写操作,由操作系统决定什么时候写} no-appendfsync-on-rewrite no #对新写的操作放在缓存队列中 auto-aof-rewrite-percentage 100 #当前的AOF文件已经是上次重写的二倍时,再重新触发一次重写操作 auto-aof-rewrite-min-size 64mb #启动新的日志重启重写过程中的最小值
2.3 重写机制
随着命令不断写入AOF,文件会越来越大,为了解决这个问题,Redis引入AOF重写机制压缩文件体积。AOF文件重写是把Redis进程内的数据转换为写命令同步到新的AOF文件的过程。
AOF重写过程可以手动触发和自动触发:
- 手动触发:直接调用 BGREWRITEAOF命令。
- 自动触发:根据auto-aof-rewrite-min-size 和 auto-aof-rewrite-percentage参数确定自动触发时机.
- auto-aof-rewrite-min-size :表示AOF重写时文件最小值,默认为64MB
- auto-aof-rewrite-percentage:当前AOF文件已经是上次重写的二倍时,再重新触发一次重写操作
2.4 流程说明
1)Redis主进程通过fork创建子进程;
2)子进程根据Redis内存中的数据穿件数据库重建命令序列临时文件中
3)父进程继续接受客户端请求,并会把这些请求中的写操作继续追加至原来的AOF文件,额外的,这些新的写请求还会放置一个缓存队列中
4)子进程重写完成,会通知父进程,父进程把缓冲中的命令写到临时文件中
5)父进程用临时文件替换老的aof文件不会读取正在使用AOF文件,而通过将内存中的数据以命令的方式保存在临时文件中,完成之后替换原来的AOF文件
2.5 文件校验
加载损坏的AOF文件时会拒绝启动,并打印日志:
# Bad file format reading the append only file: make a backup of your AOF file, then use ./redis-check-aof --fix <filename>
运维提示:
对于错误格式的AOF文件,先进行备份,然后采用redis-check-aof--fix命令进行修复,修复后使用diff-u对比数据的差异,找出丢失的数据,有些可以人工修改补全
AOF文件可能存在结尾不完整的情况,比如机器突然掉电导致AOF尾部文件命令写入不全。Redis为我们提供了aof-load-truncated配置来兼容这种情况,默认开启。加载AOF时,当遇到此问题时会忽略并继续启动,同时打印如下警告日志:
# !!! Warning: short read while loading the AOF file !!!
# !!! Truncating the AOF at offset 397856725 !!!
# AOF loaded anyway because aof-load-truncated is enabled