redis持久化机制

Redis持久化

持久化的功能就是为了避免进程退出,而导致内存中的数据永久丢失,需要定期将redis中的数据以某种形式从内存保存到硬盘;那么就可以在下次重启时通过这些持久化文件还原数据。另外,一般为了灾难备份,都会将文件拷贝到其他远程位置。

RDB持久化

触发条件

  • 手动触发

    有两个命令save和bsave都可以进行手动持久化。

    他们之间的区别在于:
    save命令会阻塞redis服务器进程,知道RDB文件创建完毕为止,缺点在于此阶段将不能处理任何命令请求;
    bsave顾名思义就是backgroud save的意思,即后台备份,bsave会从主线程fork一个子线程(fork进程的时候依然会阻塞服务器,但时间相比直接save短了很多),由子线程来进行创建RDB文件,主线程则继续处理请求。

  • 自动触发

    自动触发需要在配置文件中配置save m n,其含义为当在m秒内发生了n此变化时,将会触发bsave;如save 100 10:当在100秒内发生了10此变化时,将会触发bsave。

  • 其他触发
    在主从复制的场景下,当从节点执行全量复制操作,那么主节点将会执行bsave,并将RDB文件发送给从节点。
    另外执行shutdown命令时,也会执行RDB持久化。

bsave的执行流程

  • redis父进程首先判断当前是否正在执行save,bsave或者bgrewriteaof,如果是,那么则直接返回。
  • 父进程fork创建子进程,此过程父进程是阻塞的,不响应其他命令
  • fork完成后子进程创建RDB文件,根据父进程内存快照生成临时快照文件,完成后对原有的RDB文件进行原子替换。
  • 子进程发送完成信号给父进程,父进程更新save信息。

RDB文件的加载

RDB文件的载入工作是在服务器启动时自动执行的,并没有专门的命令。但是由于AOF的优先级更高,因此当AOF开启时,Redis会 优先载入AOF文件 来恢复数据;只有当AOF关闭时,才会在Redis服务器启动时检测RDB文件,并自动载入。服务器载入RDB文件期间处于阻塞状态,直到载入完成为止。
Redis载入RDB文件时,会对RDB文件进行校验,如果文件损坏,则日志中会打印错误,Redis启动失败。

AOF持久化

AOF相比于RDB不同的是,RDB是存数据快照,而AOF则是存写命令;当redis重启后可以执行AOF文件中的写命令来回复数据,与RDB相比,AOF的实时性更好,已成为主流的持久化方案。

redis默认开启RDB,关闭AOF;如果需要开启AOF,请在配置文件中加上:
appendonly yes

执行流程

因为AOF模式需要记录redis的每条写命令,所以开启后不存在手动触发模式;

1. 命令追加(append)
redis首先将写命令追加到缓冲区aof_buf,不直接写入文件

2. 文件写入(write)和文件同步(sync)
为了提高文件写入效率,在现代操作系统中,当用户调用write函数将数据写入文件时,操作系统通常会将数据暂存到一个内存缓冲区里,当缓冲区被填满或超过了指定时限后,才真正将缓冲区的数据写入到硬盘里。这样的操作虽然提高了效率,但也带来了安全问题:如果计算机停机,内存缓冲区中的数据会丢失;因此系统同时提供了fsync、fdatasync等同步函数,可以强制操作系统立刻将缓冲区中的数据写入到硬盘里,从而确保数据的安全性。

AOF缓存区的同步文件策略由参数appendfsync控制,各个值的含义如下:

  • always
    命令写入aof_buf后立即调用系统fsync操作同步到AOF文件,fsync完成后线程返回。这种情况下,每次有写命令都要同步到AOF文件,硬盘IO成为性能瓶颈,严重降低了Redis的性能;缓冲区似有若无。
  • no
    命令写入aof_buf后调用系统write操作,不对AOF文件做fsync同步;同步由操作系统负责,通常同步周期为30秒。这种情况下,文件同步的时间不可控,且缓冲区中堆积的数据会很多,数据安全性无法保证。
  • everysec
    命令写入aof_buf后调用系统write操作,write完成后线程返回;fsync同步文件操作由专门的线程每秒调用一次。everysec是前述两种策略的折中,是性能和数据安全性的平衡,因此是Redis的默认配置,也是我们推荐的配置。

3. 文件重写(rewrite)
随着时间流逝,Redis服务器执行的写命令越来越多,AOF文件也会越来越大;过大的AOF文件不仅会影响服务器的正常运行,也会导致数据恢复需要的时间过长。

文件重写是指定期重写AOF文件,减小AOF文件的体积。需要注意的是,AOF重写是把 Redis进程内的数据转化为写命令,同步到新的AOF文件;不会对旧的AOF文件进行任何读取、写入操作。
文件重写之所以能够压缩AOF文件,原因在于:

  • 过期的数据不再写入文件
  • 无效的命令不再写入文件:如有些数据被重复设值(set mykey v1, set mykey v2)、有些数据被删除了(sadd myset v1, del myset)等等
  • 多条命令可以合并为一个:如sadd myset v1, sadd myset v2, sadd myset v3可以合并为sadd myset v1 v2 v3。不过为了防止单条命令过大造成客户端缓冲区溢出,对于list、set、hash、zset类型的key,并不一定只使用一条命令;而是以某个常量为界将命令拆分为多条。

文件重写的触发:

  • 手动触发:直接调用bgrewriteaof命令
  • 自动触发:根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数,以及aof_current_size和aof_base_size状态确定触发时机

启动时加载

当AOF开启时,Redis启动时会优先载入AOF文件来恢复数据;只有当AOF关闭时,才会载入RDB文件恢复数据。
当AOF开启,但AOF文件不存在时,即使RDB文件存在也不会加载。

posted @ 2022-02-28 13:52  码出地球  阅读(129)  评论(0编辑  收藏  举报