文章目录
RDB
RDB持久化是把当前进程数据生成快照存到硬盘的过程,触发rdb持久化分为手动触发和自动触发
触发机制
手动触发对应的命令save和bgsave
-
save:阻塞当前redis服务,知道rdb的过程完成为止,对于内存比较大的数据或者实例会造成上时间的堵塞
-
bgsave:redis进程会fork一个子进程,rdb持久化过程由子进程负责,完成后自动结束。阻塞只会发生在fork阶段,时间一般都很短
自动触发
-
使用save的相关配置,如"save m n" 表示在m秒内数据存在n次修改时,会自动触发bgsave
-
如果从节点执行完全复制操作,主节点自动执行bgsave生成rdb文件并发送给从节点
-
执行debug reloade 命令重新加载redis时,也会自动触发save操作
-
默认情况下执行shutdown 命令时,如果没有开启aof持久化时,则自动执行bfsave。
rdb流程
-
执行bgsave命令,redis父进程会判断当前是否有正在执行的子进程,如果有就直接返回
-
父进程执行fork一个子进程,在fork过程中父进程会阻塞,可以通过 info stats命令,查看_fork_usec,可以获取最近一个fork的耗时记录
-
父进程fork完成后,bgsave会返回一个信息,父进程可以继续响应其他的命令
-
子进程创建rdb文件,根据父进程内存生成临时的快照文件,完成后会对原文件进行原子替换
-
子进程发送信号给父进程表示完成
优缺点
rdb优点
-
rdb是一个紧凑的二进制文件,代表redis在某个时间点上的数据快照,适合做数据备份,全量复制等场景
-
redis在加载rdb恢复数据远远快于aof的方式。
rdb缺点
- rdb没有办法对数据做到实时或者秒级持久化,每次都要fork操作创建子进程,属于重量级操作
AOF
aof以独立日志的方式记录每次写命令(不是数据,而是命令),重启时再重新执行aof文件中的命令用于恢复数据的目的。aof也解决了rdb无法实时或者秒级操作的处理。
aof使用
开启aof需要在配置文件中配置:appendonly yes,默认是关闭的状态。aof文件名appendfilename配置,默认是的是appendonly.aof
aof的工作流程:命令写入(append),文件同步(sync),文件重写(rewrite),重启加载(load)。
-
所有的写入命令会追加到aof_buf中
-
aof_buf 根据对应的策略向硬盘做同步操作
-
随着aof文件越来越大,需要定期的对aof文件重写,压缩文件
-
当redis服务器重启时,可以加载aof文件进行数据恢复
命令写入(append)
aof命令写入的内容是以文本协议格式
aof为什么使用文本协议格式
-
文本协议具有很好的兼容性
-
所有的写入命令包括追加操作,用文本协议格式,避免了二次处理开销
-
文本协议具有可读性,方便修改和处理
aof为什么要把命令追加到aof_buf中
- redis使用单线程方式处理命令,如果每次写aof文件命令都会直接追加到硬盘,性能完全取决于当前硬盘的负载
文件同步
redis提供了多种奥法缓冲区同步文件策略,由appendfsync参数控制
-
everysec:命令写入aof_buf后调用系统write操作,write完成后线程返回。fsync同步操作,由专门线程每秒调用一次
-
always:命令写入aof_buf后调用系统fsync操作,同步到aof文件,fsync完成后线程返回
-
no:命令写入aof_buf后调用系统write操作,不对aof文件做同步操作,同步硬盘操作由操作系统负责,同步周期最长为30秒
-
配置为everysec,是默认配置,也是最优的同步策略,但是在系统宕机的情况下理论理论情况下会丢失1秒的数据,实际上最多丢失2秒
-
配置为always,每次写入都要同步aof文件,会降低redis高性能特性,不建议配置
-
配置为no,由于每次同步aof文件的时间是不确定的,而且会加大每次同步硬盘的数据量,但是数据不发保证安全性
重写机制
随着命令的不断写入到aof中,文件会越来越大,为了解决这个问题,redis对aof引入了重写机制压缩文件的大小。aof重写是把redis进程内的数据转换为写命令同步到新的aof文件的过程
aof重写后文件变小的原因大概有三点
-
进程内已经超时的数据不写入文件
-
旧的aof文件中,包含无效了命令,如del hdel等,重写使用进程内数据直接生成,aof文件只保留最终写入数据的命令
-
多条命令可以合成一个命令
aof重写的过程可以手动和自动触发
手动触发:直接调用bgrewriteaof命令
自动触发:根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数确定自动触发时机
auto-aof-rewrite-min-size:表示aof重写时文件文件最小体积,默认为64mb
auto-aof-rewrite-percentage:代表当前aof文件空间和上一次重写后的aof文件空间的比值
自动触发时机 = aof_current_size > auto-aof-rewrite-min-size && (aof_current_size-aof_base_size) / aof_base_size >= auto-aof-rewrite-percentage
流程说明:
-
执行aof重写
-
父进程执行fork创建子进程
-
主进程fork子进程后,继续响应其他的命令,所有的又该命令依旧写入aof缓冲区中,并根据appendfsync策略同步到硬盘中,保证原有aof机制的正确性
-
由于fork操作运用写时复制技术,子进程只能共享fork操作时的内存数据,由于父进程依旧响应命令,所以redis会保存这部分命令,防止新的aof文件生成期间丢失这部分的命令
-
子进程根据内存快照,按照命令合并规则写入到新的aof文件,每次批量写入硬盘数据量由配置 aof-rewrite-incremental-fsync控制,防止单次刷盘数据过多造成硬盘阻塞
-
新aof文件写入完成后,子进程发送信号给父进程
-
父进程再把aof重写缓冲区的数据写入到新的aof文件中
-
使用新的aof文件替换老文件,就完成aof重写
重启加载
aof和rdb都是用于服务器重启时恢复数据
流程说明
-
aof持久化开启并存在aof文件时,优先加载aof文件,日志:append only
-
aof没有开启时且存在rdb文件,就加载rdb文件,日志:disk
-
加载文件成功后,redis启动,加载失败,则启动失败
AOF追加阻塞
开启aof持久化时,默认的同步策略everysec,当系统资源资源繁忙时,会造成reids主线程阻塞
阻塞流程
-
主线程负责写入aof缓冲区
-
aof线程负责每秒执行一次同步磁盘操作,并记录最近一次同步时间
-
主线程负责对比上一次aof同步时间
-
如果距上次同步成功时间在2秒内,主线程直接返回
-
如果距上次同步成功时间超过2秒,主线程将会阻塞,直到同步操作完成
仅供自己学习使用,如有侵权,请及时联系我删除