目录:
前言
Redis支持RDB和AOF两种持久化机制,持久化能够有效避免因进程退出而造成的数据丢失问题,说白了就是将内存上的数据保存到硬盘上,等待下次加载时再将内存上的数据读取出来
RDB
RDB持久化是把当前进程数据生成快照保存到硬盘的过程,触发RDB持久化分为手动触发亦或者自动触发
手动触发:
- bgsave:Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只在fork阶段
- save :阻塞当前Redis服务器,直到RDB过程完成位置
Redis内部所有设计RDB操作都采用类似bgsave的方式,即不影响Redis的服务
自动触发:
- 使⽤save配置。如"save m n"表⽰m秒内数据集发⽣了n次修改,⾃动RDB持久化
- 从节点进⾏全量复制操作时,主节点⾃动进⾏RDB持久化,随后将RDB⽂件内容发送给从结点
- 执⾏shutdown命令关闭Redis时,执⾏?RDB?持久化
bgsave的命令运作流程:
- 执行bgsave命令,Redis父进程判断当前进程是否存在其他执行的子进程,如RDB/AOF子进程,有的话bgsave直接返回了
- 父进程执行fork创建子进程,fork过程中父进程会被阻塞,fork的耗时的单位为微秒~~
- 父进程fork完成后,bgsave命令返回"Background saving started"信息,并不再阻塞父进程
- 子进程创建RDB文件,根据父进程内存生成临时的快照文件,完成后对原有文件进行原子替换(lastsave 命令可以获取最后一次生成RDB文件的时间)
- 进程发送信号给父进程表示完成,父进程更新统计信息
Redis的默认Config目录:
在ubuntu下Redis的默认配置目录:
/etc/redis/redis.conf
这里可以修改Redis的配置文件的目录:
不建议乱改嗷~~
RDB文件的处理:
保存目录:
默认保存在 [ /var/lib/redis ] 下
下面这里是redis.conf中生成rdb文件的配置项~~
文件名通过dbfilename配置指定(默认dump.rdb)
压缩:
Redis默认采用LZF算法对生成的RDB文件做压缩处理,压缩后的文件远远小于内存大小,默认开启,可以通过
tip:虽然压缩会消耗cpu,但可以大幅降低文件体积,方便通过网络发送到从节点,建议打开
校验:
如果Redis启动加载到损坏的RDB文件会拒绝启动。这时候就可以使用Redis提供过的redis-check-dump工具检测RDB文件并获取对应的错误报告~
RDB文件的自动保存设置:
同样是在配置文件当中:
RDB文件的优缺点:
- RDB是一个紧凑压缩二进制文件,代表Redis某个时间上的数据快照。非常适用与备份,全量复制的场景。比如你每天手机自动同步一次相册到云相册那样的意思
- Redis加载RDB恢复数据远远快于AOF,因为RDB是二进制文件~
- RDB方式数据没办法做到实时持久化。因为bgsave每次运行都要fork的,属于重量级操作,太过于频繁的全量复制,对服务器的cpu和硬盘复核很大
- RDB文件使用特定的二进制格式保存,Redis版本演进过程中有多个RDB版本,兼容性可能有冲突
AOF
AOF(Append Only File)持久化:以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中的命令达到恢复数据的目的。AOF主要作用就是解决的数据持久化的实时性,目前已经是Redis持久化的主流方式
开启AOF:
开启AOF功能需要设置配置:appendonly yes,默认不开启。
开启AOF功能需要设置配置:appendonly yes,默认不开启。AOF⽂件名通过appendfilename
配置(默认是appendonly.aof)设置。保存⽬录同RDB持久化⽅式⼀致,通过dir配置指定。AOF的⼯作流程操作:命令写⼊(append)、⽂件同步(sync)、⽂件重写(rewrite)、重启加载(load)
AOF工作流程:
- 将输入的命令加入到AOF缓冲区(aof_buf)中
- AOF缓冲区根据不同策略向硬盘进行同步操作
- 随着AOF文件增大,会定期对AOF文件进行重写(rewrite)来进行压缩
- 重新启动的时候就可以加载对应的AOF文件
Q:AOF过程为什么要提供缓冲区?
A:首先要知道Redis设计师单线程响应,如果每次AOF文件都直接跟文件进行IO,性能会大打折扣,所以就先存着,数量到了一起IO,因此Redis也给用户提供了不同的缓冲同步策略,用户可以根据场景来自行判断使用
AOF缓冲区同步文件策略:
配置项 | 说明 |
---|---|
always | 命令写入到aof_buf后调用fsync同步 |
everysec | 命令写入到aof_buf后只执行write操作,不进行fsync。每秒由同步线程进行fsync |
no | 命令写入aof_buf后只执行write操作,由OS控制fsync频率 |
系统调用write和fsync说明:
- write操作会出发延迟写机制。Linux内核提供页缓冲区用来保证硬盘IO性能。write操作在写入系统缓冲区后就会返回。什么时候同步看操作系统怎么调度。如果在这期间服务器挂了,那数据就没有了
- Fsync针对单个文件做强制的硬盘同步,fsync将阻塞直到数据写入到硬盘
所以上面的的三个配置项可以这么解释
always:只要缓冲区有东西我就马上写入到硬盘中持久化起来,非常的频繁,只有珍贵数据这样做
no:什么时候同步看OS,同步时间不可控,虽然提高了性能但是对文件的保护也下降不少
everysec:这个是默认配置,理论上最多丢失1s内的数据,平衡了数据和性能
重写机制:
着命令不断写⼊AOF,⽂件会越来越⼤,为了解决这个问题,Redis引⼊AOF重写机制压缩⽂件体积。AOF⽂件重写是把Redis进程内的数据转化为写命令同步到新的AOF⽂件。
Q:怎么重写后就能让AOF的文件变小,怎么做到的??
A:
- 超时数据不写入文件,比如set k1 one 后 又ket k1 two 那么第一次的set就是超时数据
- 旧的AOF中的无效命令,例如del,hdel,srem之类,比如set k1 后 del k1,那么这两个命令加起来就是无效命令了
- 多条合并为一条,例如:lpush my_list fir,lpush my_list sec,lpush my_list thr直接变成一条命令lpush my_list fir sec thr
你知道的这个文件在保证数据正确的前提下当然越小越好~~
较⼩的AOF⽂件⼀⽅⾯降低了硬盘空间占⽤,⼀⽅⾯可以提升启动Redis时数据恢复的速度
重写流程:
1.执行AOF重写请求。如果当前进程正在执行了AOF重写,直接返回。如果当前进程正在bgsave,那么重写就延迟到bgsave后执行
2.父进程开始fork后继续保持原来工作
3.开始重写咯
a.主进程fork之后,继续响应其他命令,所有的修改操作一并写入到aof_buf 和 aof_rewrite_buf中,此时要保证旧的AOF文件正确
b.子进程fork之后写入完新的AOF文件后,再把aof_rewrite_buf中的缓冲区也加进去,组合成一个完整的aof文件
4.重写完成
同时开启RDB和AOF的数据恢复形式
可以看出如果RDB和AOF同时开启那么AOF优先~~
小结
1.Redis提供了两种持久化方案:RDB和AOF
2.RDB视为内存快照,占用空间小,恢复速度快,但生产代价高
3.AOF视为对修改命令的保存,在恢复时重新执行命令。并且拥有重写机制来压缩AOF文件
4.RDB和AOF都使用fork创建子进程应用,利用子进程拥有父进程的内存快照的特点进行持久化