第五章 持久化
Redis拥有如此高的性能跟它将数据保存在内存中是由很大关系的,但在生产环境中,需要考虑到各种突发事件,比如停电和进程意外退出,
如果没有相应的对策,存在内存的数据就会消失,这个时候就会用到Redis持久化的策略。而且Redis的持久化策略并不仅仅用来实现数据恢
复,在后续的学习中Redis的复制也会用到持久化策略。
Redis的持久化策略主要分为:
- RDB
- AOF
5.1.RDB
5.1.1.RDB触发方式
RDB的策略是将当前数据快照保存在本地硬盘中,触发RDB的方式有两种:
- 手动触发
- 自动触发
手动触发
手动触发主要通过执行两个命令实现,save和bgsave
- save:阻塞执行,直到RDB任务结束才能继续执行,因为Redis是单线程架构的,所以这样会造成阻塞
- bgsave:主进程不参与持久化操作而是fork一个子进程来执行操作,而fork操作的消耗的时间一般很短,这样就不会产生阻塞
因为save容易产生阻塞问题,所以已经被废弃
自动触发
1) 从节点执行全量复制(复制主机点)操作,主节点bgsave产生一个RDB文件让从节点复制数据
2) 执行shutdown命令后,如果没有配置AOF则默认自动执行bgsave产生RDB,防止数据丢失
5.1.2.bgsave流程
1) 执行bgsave,父进程判断是否有正在执行的子进程,如果存在则直接返回
2) fork产生一个子进程(这个过程会阻塞父进程,但时间很短)
3) fork完成后,父进程继续响应操作
4) 子进程创建RDB文件
5) 子进程向父进程发送信号表示操作完成
5.1.3.RDB的优缺点
优点
- 为紧凑压缩的二进制文件,适合用来备份和全量复制。通过定期执行bgsave,用来实现灾难恢复
- 加载RDB数据比AOF更快
缺点
- 没有办法做到实时备份,因为fork进程开销过大
5.2.AOF(Append Only File)
用日志的方式记录写命令,通过重新执行AOF文件来恢复数据.开启AOF很简单,就需要修改配置文件项中的appendonly yes即可。
执行流程
1) 所有写命令会缓存到aof_buf中去
2) AOF缓冲区根据策略向磁盘同步
3) 随着AOF文件的膨胀,需要定期rewrite来减小文件大小
4) Redis文件重启时加载AOF来恢复数据
命令写入
1) AOF写入采取文本协议格式,主要为了保证兼容性和避免二次开销
2) 采用缓冲区的理由:因为硬盘的存储速率会严重影响Redis性能,存在缓冲区能改善这个问题.
同步策略
- always:每次执行写命令就要向硬盘同步AOF,这样性能会很差(硬盘速率远远不如内存)
- everysec:默认策略,每秒钟向硬盘同步,这样最多只会丢失1秒的数据
重写机制
前面说了重写是为了压缩提及,不然随着时间的推移AOF文件会越来越大
rewrite后文件变小的原因
1) 过期的数据不再写入文件
2) 旧的AOF包含无效命令,比如删除操作(因为现在的数据是AOF文件中命令执行的结果,所以就不需要这些无效命令,直接根据当前数据进行添加即可,这样只用保留写入命令)
3) 多条命令可以合并成一条命令 lpush list a,lpush list b => lpush list a b
重写机制的触发
- 手动触发:调用bgrewriteaof命令
- 自动触发:设置参数auto-aof-rewrite-min-size(默认64M)和auto-aof-rewrite-percentage(当前AOF文件大小与上次rewrite之后的文件大小的比值)来确定触发时机
重写流程
1) 执行AOF重写请求
1-1.如果当前进程正在执行AOF重写,则直接返回
1.2.如果正在执行bgsave命令,则等到bgsave完成后再执行
2) 父进程执行fork操作
3) fork完成之后
3-1.将写命令写入aof_buf中,同时根据同步策略同步到硬盘中
3-2.因为Redis采取了写时复制技术,这时使用父进程通过AOF重写缓冲区来保存fork期间产生的新数据
4) 子进程通过内存快照写入新的AOF文件中
5) AOF写入完成
5-1.子进程发信号给父进程,父进程更新统计信息
5-2.父进程把AOF重写缓存区的数据append到新的AOF文件中
5.3.使用新的AOF文件替换老的AOF文件
5.3.重启加载
1) 如果开启了AOF且存在AOF文件则优先加载AOF文件
2) 未开启AOF或者AOF文件不存在则加载RDB文件
3) 加载AOF/RDB成功/失败