《Redis开发与运维》第五章笔记

129 阅读4分钟
原文链接: idealv.github.io

第五章 持久化

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成功/失败