Redis持久化机制

Redis支持RDB和AOF两种持久化机制,持久化功能有效地避免因进程退出造成的数据丢失问题,当下次重启时利用之前持久化文件即可实现数据恢复。

1. RDB持久化

RDB持久化是把当前进程数据生成快照保存到硬盘的过程,触发RDB持久化过程分为手动触发和自动触发。

RDB持久化功能所生成的RDB文件是一个经过压缩的二进制文件,通过该文件可以还原生成RDB文件时的数据库状态。

1.1 RDB文件的创建与载入

有两个Redis命令可以用于生成RDB文件,一个是SAVE,另一个是BGSAVE.

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

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

RDB文件的载入工作是在服务器启动时自动执行的,Redis没有专门用于载入RDB文件的命令,只要Redis服务器在启动时检测到RDB文件存在,它就会自动载入RDB文件。

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

  • 如果服务器开启了AFO持久化功能,那么服务器会优先使用AFO文件来还原数据库状态。
  • 只有在AFO持久化功能处于关闭状态时,服务器才会使用RDB文件来还原数据库状态。

image-20210305104729387

1.2 SAVE命令执行时服务器状态

SAVE命令执行时,Redis服务器会被阻塞,这时服务器不能处理任何命令请求。

1.3 BGSAVE命令执行时服务器状态

BGSAVE命令执行期间,服务器仍可以处理客户端的命令请求。但是,对SAVEBGSAVEBGREWRITEAOF这三个命令方式和平时有所不同。

BGSAVE命令执行期间,SAVE命令会被服务器拒绝,这是为了避免父进程和子进程同时执行两个rdbSave调用,防止产生竞争条件。

BGSAVE命令执行期间,BGSAVE命令也会被服务器拒绝,因为通知执行两个BGSAVE命令也会产生竞争条件。

最后,BGREWRITEAOFBGSAVE两个命令不能同时运行:

  • 如果BGSAVE命令正在执行,那么客户端发送的BGREWRITEAOF命令会被延迟到BGSAVE命令执行完毕之后执行。
  • 如果BGREWRITEAOF命令正在执行,那么客户端发送的BGSAVE命令会被服务器拒绝。

1.4 RDB文件载入时服务器状态

服务器在载入RDB文件期间,会一直处于阻塞状态,直到载入工作完毕为止。

1.5 自动间隔性保存

因为BGSAVE可以在不阻塞服务器进程下执行,所以允许设置save选项,让服务器每隔一段时间自动执行一次BGSAVE命令。

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

比如下面例子:

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

saveparams属性

saveparams属性是一个数组,数组中的每个元素都是一个saveparam结构,每个saveparam结构都保存了一个save选项设置的保存条件:

struct saveparam {
    time_t seconds;	// 秒数
    int changes;	// 修改数
}

dirty计数器和lastsave属性

  • dirty计数器记录距离上一次成功执行SAVE命令或者BGSAVE命令后,服务器对数据库状态(所有数据库)进行了多少次修改(删除,更新,写入等)
  • lastsave属性是一个UNIX时间戳,记录了服务器上一次成功执行SAVE或者BGSAVE命令的时间。
struct redisServer {
    long long dirty;	// 修改计数器
    time_t lastsave;	// 上一次执行保存的时间
}

检查保存条件是否满足

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

1.6 RDB文件结构

image-20210305135556398

  • REDIS部分长度为5个字节,保存着REDIS五个字符。通过这五个字符,程序在载入文件时,快速检查所载入的文件是否RDB文件。
  • db_version长度为4个字节,它的值是一个字符串表示的整数,这个整数记录了RDB文件的版本号。比如0006代表RDB文件版本为第六版。
  • database部分包含零个或任意多个数据库,以及各个数据库中的键值对数据。
    • 如果服务器数据库状态为空,这个部分也为空,长度为0字节。
    • 如果服务器数据库状态为非空(有至少一个数据库非空),那么这个部分也为非空。根据数据库保存的键值对的数量、类型和内容的不同,这个部分长度也会有所不同。
  • EOF常量的长度为1字节,标志着RDB文件正文内容的结束,当读入程序遇到这个值的时候,表明所有数据库的所有键值对都已经载入完毕了。
  • check_sum是一个8字节长的无符号整数、保存着一个校验和,这个校验和是程序通过对REDISdb_versiondatabasesEOF四个部分的内容进行计算得出的。服务器在载入RDB文件时,会将载入数据所计算出的校验和与check_sum所记录的校验和进行对比,以此来检查RDB文件是否有出错或者损坏的情况出现。

databases部分

一个RDB文件的databases部分可以保存任意多个非空数据库。

例如,如果服务器的0号和3号数据库非空,则将创建以下结构RDB文件:

image-20210305141958845

每个database都包含数据库所有键值对。

每个非空数据库在RDB文件中都可以保存为SELECTDBdb_numberkey_value_pairs三个部分。

image-20210305142202954

  • SELECTDB常量的长度为1字节,标示将要读入的数据库号码。
  • db_number保存着一个数据库号码,根据号码大小不同,这个部分长度可以是1字节、2字节、5字节等。当程序读入db_number部分后,服务器会调用SELECT命令,根据读入的数据库号码进行数据库的切换,使得读入的键值对可以正确载入到数据库中。
  • key_value_pairs部分保存了数据库中所有键值对数据,如果键值对带有过期时间,则过期时间也会和键值对保存在一起。根据键值对的数量、类型、内容以及是否有过期时间等条件的不同,key_value_pairs部分的长度也会有所不同。

key_value_pairs部分

RDB文件中的每个key_value_pairs部分都保存了一个或以上数量的键值对,如果键值对带有过期时间的话,那么键值对的过期时间也会被保存在内。

不带过期时间的键值对如下:
image-20210305202119931

  • TYPE记录了value类型,长度为1字节。
  • KEY总是一个字符串对象。
  • 根据TYPE类型不同,以及保存内容长度的不同,保存value的结构和长度也会有所不同

带有过期时间的键值对如下:

image-20210305202032401

  • EXPIRETIME_MS常量的长度为1字节,它告知读入程序,接下来要读入的是一个以毫秒为单位的过期时间。
  • ms是一个8字节长的带符号整数,记录着一个以毫秒为单位的UNIX时间戳,这个时间戳就是键值对的过期时间。

2. AOF持久化

AOF持久化是通过保存Redis服务器所执行的写命令来记录数据库状态的。

2.1 AOF持久化的实现

命令追加

AOF打开后,服务器在写完一个命令之后,会以协议格式将被执行的写命令追加到服务器状态的aof_buf缓冲区末尾。

AOF持久化的效率和安全性

通过配置appendfsync选项的值直接决定AOF持久化功能的效率和安全性。

  • 值为always时,服务器每个事件循环都要将aof_buf缓冲区中的内容写入到AOF文件,并且同步AOF文件。always的效率最低,但是安全性最高。
  • 值为everysec时,服务器在每个事件循环都将aof_buf缓冲区中所有内容写入到AOF文件,并且每隔一秒就要在子线程中对AOF文件进行一次同步。效率上足够快,就算故障,也只是丢失一秒中的命令。
  • 值为no时,服务器在每个事件循环都将aof_buf缓冲区中所有内容写入到AOF文件,至于何时同步,就有操作系统控制。

2.2 AOF文件的载入与数据还原

AOF文件如果出现错误,则redis不会正常启动,可以使用redis-check-aof --fix修复appendonly.aof

image-20210305210234588

2.3 AOF文件重写

AOF中的内容会随着时间越来越大,所以要对AOF文件进行重写整理。用新的AOF文件来替代现有的AOF文件。

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb	# aof文件大于64mb会重写

实现原理:首先从数据库中读取键现在的值,然后用一条命令去记录键值对,代替之前记录这个键值对的多条命令。

AOF文件重写程序是在子进程中执行的:

  • 子进程重写期间,服务器进程可以继续处理命令请求
    AOF中的内容会随着时间越来越大,所以要对AOF文件进行重写整理。用新的AOF文件来替代现有的AOF文件。

3. 参考资料

  • 《Redis设计与实现》
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值