Redis-持久化

Redis-持久化

一、RDB持久化

        为了解决服务器进程退出导致数据丢失,Redis提过了RDB持久化功能,可以将Redis在内存中的数据保存到磁盘中,避免数据意外丢失。

        RDB持久化既可以手动执行,也可以根据服务器配置选项定期执行,该功能将某个时间点上的数据库状态保存到一个RDB文件中。生成的RDB文件是一个经过压缩的二进制文件,通过该文件,可以还原生成RDB文件时的数据库状态。

1、RDB文件的创建与载入

命令:SAVE、BGSAVE

        SAVE 命令会阻塞Redis服务器进程,直到RDB文件创建完毕为止,在服务器进程阻塞期间,服务器不能处理任何命令请求。

        BGSAVE 命令会派生一个子进程,然后由子进程负责创建RDB文件,服务器进程继续处理命令请求。

        创建RDB文件的实际工作由rdb.c/rdbSave函数完成,SAVE命令和BGSAVE命令会以不同的方式调用这个函数。

        RDB文件的载入工作是在服务器启动时自动执行,只要Redis服务器在启动时检测到RDB文件存在,就会自动载入RDB文件。

因为AOF文件更新频率通常比RDB文件更新频率高,所以:

1)如果服务器开启了AOF持久化公共能,那么服务器会优先使用AOF文件来还原数据库状态

2)只有在AOF持久化功能关闭状态时,服务器才会使用RDB文件来还原数据库状态

当SAVE命令执行时,Redis服务器会被阻塞,客户端发送的所有命令请求都会被拒绝

当BGSAVE命令执行时,Redis服务器任然可以继续处理客户端命令请求,但是,在BGSAVE命令执行期间,服务器处理SAVE、BGSAVE、BGREWRITEAOF三个命令的方式会和平时有所不同。

        1)在BGSAVE命令执行期间,客户端发送的SAVE命令会被服务器拒绝

        2)在BGSAVE命令执行期间,客户端发送的BGSAVE命令会被服务器拒绝

        3)BGREWRITEAOF和BGSAVE命令不能同时执行:如果BGSAVE 命令正在执行,BGREWRITEAOF命令会被延迟到BGSAVE命令执行完毕之后执行;如果BGREWRITEAOF命令正在执行,BGSAVE命令会被服务器拒绝

服务器载入RDB期间,会一直处于阻塞状态。

2、自动间隔性保存

        因为BGSAVE命令可以在不阻塞服务器进程的情况下执行,所以Redis允许用户通过设置服务器配置的save选项,让服务器每隔一段时间自动执行BGSAVE命令。

        用户可以通过save选项设置多个保存条件,只要其中一个条件被满足,服务器就会执行BGSAVE命令。

2.1、设置保存条件

        当服务器启动时,用户可以通过指定配置文件或传入参数的方式设置save选项,如果用户没有主动设置save选项,服务器默认设置

        save  900  1             (服务器在900秒之内,对数据库进行了至少1次修改)

        save  300  10         (服务器在300秒之内,对数据库进行了至少10次修改)

        save  60  10000     (服务器在60秒之内,对数据库进行了至少10000次修改)

        服务器程序会根据save选项所设置保存条件,设置服务器状态redisServer的saveparams属性。

2.2、dirty计算器和lastsave属性

        dirty计数器 记录距离上一次成功执行SAVE或BGSAVE命令之后,服务器对数据库状态进行了多少次修改(包括写入、删除、更新操作)

        lastsave属性 是一个UNIX时间戳,记录服务器上一次成功执行SAVE命令或者BGSAVE命令的时间

2.3、检查保存条件是否满足

        Redis的服务器周期性操作函数serverCron默认100毫秒执行一次,该函数用于对正在运行的服务器进行维护,其中一项工作就是检查save选项所设置的保存条件是否满足,如果满足,就执行BGSAVE命令。

3、RDB文件结构

RDB文件最开头是REDIS部分,这个部分的长度为5字节,保存"REDIS"五个字符。通过这5个字符,判断载入的文件是否RDB文件。

db_version长度4字节,是一个字符串表示的整数,记录RDB文件的版本号

databases部分包含零个或任意多个数据库,以及各个数据库中的键值对数据:

        1)如果服务器的数据库状态为空,则这个部分为空,长度为0字节

        2) 如果服务器的数据库状态为非空,那么这个部分也为非空,根据键值对数量、类型和内容不同,长度也会有所不同

EOF常量长度为1字节,标志RDB文件正文内容结束

check_sum是一个8字节的无符号整数,保存一个校验值,是通过对REDIS、db_version、databases、EOF四个部分内容计算得到,用来检查文件是否损坏。

databases部分

        一个RDB文件的databases部分可以保存任意多个非空数据库,每个非空数据在RDB文件中都可以保存SELECTDB、db_number、key_value_pairs三部分

SELECTDB常亮长度1字节,标识数据库结构的开始

db_number保存数据库号码,可以是1字节、2字节、5字节。当读入db_number部分后,会调用SELECT命令,切换到相应数据库

key_value_pairs部分保存数据库中所有的键值对数据,如果键值对带有过期时间,则过期时间和键值对保存在一起。

key_value_pairs部分

        不带过期时间的键值对由 TYPE、key、value三部分组成

        带有过期时间的键值对 由EXPIRETIMES_MS、ms、TYPE、key、value组成

        EXPIRETIMES_MS 常量,1个字节、标志接下来是一个带过期时间的键值对,单位毫秒

        ms        8字节带符号整数,记录一个以毫秒为单位的UNIX时间戳,表示键值对的过期时间

   value编码

        value部分保存一个值对象

二、AOF持久化

Redis还提供了AOF持久化功能,AOF通过保存Redis服务器所执行的写命令来记录数据库状态

1、AOF持久化的实现

        AOF持久化实现可以分为命令追加(append)、文件写入、文件同步(sync)三个步骤

1.1、命令追加

        当AOF持久化工能处于打开状态时,服务器在执行一个写命令后,会以协议格式将被执行的写命令追加到服务器状态的aof_buf缓存区的末尾

1.2、AOF文件的写入与同步

        Redis服务进程就是一个事件循环(loop),这个循环中的文件事件负责接收客户端的命令请求,以及向客户端发送的命令回复,

        因为服务器在处理文件事件时可能执行写命令,使得一些内容追加到aof_buf缓存区,所以在服务器结束一个事件循环之前,会调用flushAppendOnlyFile函数,考虑是否需要将aof_buf缓冲区中的内容写入和保存到AOF文件。

        flushAppendOnlyFile函数的行为有服务器配置的appendfsync选项决定

        如果用户没有主动设置appendfsync选项,默认为everysec。

2、AOF文件的载入与数据还原

        Redis读取AOF文件并还原数据库状态的步骤:

1)创建一个不带网络连接的客户端

2)从AOF文件中分析并读取一条写命令

3)使用步骤1创建的伪客户端执行步骤2读取的写命令

4)重复执行步骤2和步骤3,直到AOF文件中所有写命令都处理完毕。

3、AOF重写

        为了解决AOF文件体积膨胀的问题,Redis提供了AOF重写(rewirte)功能,通过该功能,可以创建一个新的AOF文件替代现有的AOF文件

3.1 、AOF重写的实现

        因为aof_rewrite函数生成的新AOF文件只包含还原当前数据库所必须的命令,所以新AOF文件不会浪费硬盘空间

3.2、AOF后台重写

        服务器直接调用aof_rewrite函数,则无法处理客户端发来的命令请求。

        为了解决后台重写数据不一致的问题,Redis服务器设置了一个AOF重写缓冲区,这个缓冲区在服务器创建子进程之后开始使用,当Redis服务器执行一个写命令之后,会同时将这个命令发送给AOF缓冲区和AOF重写缓冲区。

你可能感兴趣的:(Redis-持久化)