持久化
RDB持久化
概述
RDB,是指将内存中某一时刻的数据快照全量写入到指定的rdb文件的持久化技术。RDB持久化默认是开启的。当Redis启动时会自动读取RDB快照文件,将数据从硬盘载入到内存,以恢复Redis关机前的数据库状态
执行持久化
RDB持久化的执行有三种方式:手动save命令,手动bgsave命令,自动条件触发
使用lastsave
命令可以查看最近一次持久化的时间,其返回一个unix时间戳
- save命令
- 通过在redis-cli客户端中执行save命令,可以进行一次持久化保存。save命令在执行期间会阻塞redis-server进程,直至持久化过程完毕。在redis-server进程阻塞期间,redis不能处理任何读写请求,无法对外提供服务
- 这个同步命令可以看作是同步请求,在生产环境中一般不宜使用
- bgsave命令
- 通过在redis-cli客户端中执行bgsave命令,可以立即进行一次持久化保存。不同于save命令,该命令是在后台运行save。bgsave命令会使服务器进程redis-server生成一个子进程,由该子进程负责完成保存过程。在子进程进行保存过程中,不会阻塞redis-server进程对客户端读写请求的处理
- 自动条件触发
- 其本质上仍然是bgsave命令的执行,只不过是用户通过在配置文件中做出相应的设置后,redis会根据设置信息自动调用bgsave命令执行。
RDB优化配置
RDB相关配置在redis.conf的SNAPSHOTTING部分,官方文档及其详尽,自行翻译即可
- 保存点设置
save 3600 1 300 100 60 10000
这里添加了3个保存点,表示在60s内修改1w次及以上、300s内修改100次及以上、3600s修改1次及以上就会执行bgsave命令- 保存点之间应该是递进的包含关系
RDB文件结构
- SOF
- 是一个常量,一个字符串REDIS,只包含这五个字符,其长度为5。用于表示RDB文件的开始,以便在加载RDB文件时可以快速判断该文件是否为RDB文件
- rdb_version
- 是一个整数,长度为4字节,表示RDB文件的版本号
- databases
- 是RDB文件中的数据部分,可以包含任意多个非空数据库,每个database由三部分构成
- SODB
- 是一个常量,占1字节,标识一个数据库开始
- db_number
- 数据库编号
- key_value_pairs
- 当前数据库中的键值对数据
- 每个key_value_pairs由多个描述键值对的数据构成
- VALUE_TYPE
- 占1字节,标识该键值对中value的类型
- EXPIRETIME_UNIT
- 是一个常量,占1字节,用于标识过期时间的单位是秒还是毫秒
- time
- 当前键值对的过期时间
- EOF
- 是一个常量,占用1字节,用于标识RDB数据的结束,校验和的开始。
- check_sum
- 校验和check_sum用于判断RDB文件中的内容是否出现数据异常。其采用的是CRC校验算法
- 在持久化时,先将SOF,rdb_version及内存数据库中的数据快照这三者的二进制数据拼接起来,形成一个二进制数,在使用这个数除以校验和check_sum,此时可获得一个余数,然后将该余数拼接到之前那个二进制数后面形成databases
- 加载时,需要先用check_sum对RDB文件进行数据损坏验证。将RDB文件中除开EOF和check_sum以外的数据除以check_sum。若余数不为0则说明文件发生损坏,若为0不确定是否损坏
RDB持久化过程
对于redis默认的RDB持久化,在进行bgsave持久化时,redis-server进程会fork出一个bgsave子进程,由该子进程以异步方式负责完成持久化而在持久化过程中,redis-server进程不会阻塞,其会继续接收并处理用户的读写请求
由于子进程可以继承父进程所有资源,且父进程不能拒绝子进程的继承权。所以bgsave子进程由权读取到redis-server进程写入到内存中的用户数据,使得将内存数据持久化到dump.rdb成为可能。
bgsave子进程在持久化时首先会将内存中的全量数据copy到磁盘中的一个RDB临时文件,copy结束后,再将该文件rename为dump.rdb,替换掉原来的同名文件。
在持久化过程中,若redis-server进程接收到了用户写请求,则系统会将内存中发生数据修改的物理块copy出一个副本。等内存中的全量数据copy结束后,会再将副本中的数据copy到RDB临时文件。这个副本的生成是由于linux系统的写时复制技术实现的
AOF持久化
AOF,是指redis将每一次的写操作都以日志的形式记录到一个AOF文件中的持久化技术。当需要恢复内存数据时,将这些写操作重新执行一次,便会恢复到之前的内存数据状态。
AOF配置
AOF相关配置在redis.conf的APPEND ONLY MODE部分,要开启AOF需要将appendonly置为yes。同样的,官方给出的注释相当详尽,自行翻译即可理解。
AOF文件格式
在redis7中有三类多个AOF文件
- 基本文件
- 可以是RDF格式也可以是AOF格式。其存放的内容是由RDB转为AOF当时内存的快照数据。该文件可以有多个
- 增量文件
- 以操作日志形式记录转为AOF后的写入操作。该文件可以有多个
- 清单文件
- 用于维护AOF文件的创建顺序,保障激活时的应用顺序,该文件只有一个
增量文件扩展名为.aof,采用AOF格式。AOF格式其实就是redis通讯协议格式,AOF持久化文件的本质就是基于Redis通信协议的文本,将命令以纯文本的方式写入到文件中。
Redis协议规定,Reids文本是以行来划分,每行以\r\n行结束。每一行都有一个消息头,以标识消息类型。消息头由六种不同的符号表示
+
表示一个正确的状态信息-
表示一个错误信息*
表示消息体总共有多少行,不包括当前行$
表示下一行消息数据的长度,不包括换行符长度\r\n:
表示返回一个数值
rewrite机制
简述
rewrite是对AOF文件进行重写整理。当rewrite开启后,主进程redis-server创建出一个子进程bgrewriteaof,由该子进程完成rewrite过程。其首先对现有aof文件进行rewrite计算,将计算结果写入到一个零食文件,写入完毕后,在rename该临时文件为原aof文件名,覆盖原有文件。
策略
- 读操作命令不写入文件
- 无效命令不写入文件
- 过期数据不写入文件
- 多条命令合并写入文件
- (其实就是为了获得最终状态)
AOF优化配置
appendfsync
配置数据同步策略
- always
- 写操作命令写入aof_buf后会立即调用fsync()系统函数,将其追加到AOF文件。该策略效率低,但相对安全
- no
- 写操作命令写入aof_buf后什么也不做。而将aof_buf中的数据同步磁盘的操作由操作系统完成。linux系统默认同步周期为30s
- everysec
- 默认策略。写操作命令写入aof_buf后并不直接调用fsync(),而是每秒调用一次fsync()系统函数来完成同步
no-appendfsync-on-rewrite
刷新阈值
用于指定当AOF fsync策略设置为always或everysec,当主进程创建了子进程正在执行bgsave或bgrewriteaof时,主进程是否不调用fsync()来做数据同步。设置为no则主进程会调用fsync()做同步。yes则不会调用
若调用fsync(),在需要同步的数据量非常大时,会阻塞主进程对外提供服务,即会存在延迟问题。如果不调用fsync(),则AOF fsync策略相当于设置了no,可能会存在30s数据丢失风险
aof-rewrite-incremental-fsync
当bgrewriteaof在执行过程也是先将rewrite计算的结果写入到了aof_rewrite_buf缓存中,当缓存中的数据达到一定量后就会调用fsync()进行数据同步,将数据写入到临时文件。该属性用于控制fsync()每次同步的数据量最大不超过4MB,这样可以避免由于单次同步过大而引发的长时间阻塞
aof-timestamp-enabeld
时间戳注释
该属性设置为yes则会开启在AOF文件中增加时间戳的显示功能,可方便按照时间对数据进行恢复。但该方式可能会与AOF解析器不兼容,故默认值为no
aof-load-truncated
文件截断
当发现在加载aof文件出现错误,且错误在尾处时。若该属性设置为yes则会加载一个截断的aof文件,并且给用户报错。若设置为no则服务器会终止启动,用户需要再启动之前使用redis-check-aof工具进行修复
AOF持久化过程
- redis接收到的写操作命令并不是直接追加到磁盘的AOF文件的,而是将每一条写命令按照redis通讯协议格式暂时添加到AOF缓冲区aof_buf
- 根据设置的数据同步策略,当同步条件满足时,再将缓冲区中的数据一次性写入磁盘的AOF文件,以减少磁盘IO,提高性能
- 当磁盘的AOF文件大小达到了rewrit条件时,redis-server主进程会fork处一个子进程bgrewriteaof,由该子进程完成rewrite过程
- 子进程bgrewriteaof首先对该磁盘AOF文件进行rewrite计算,将计算结果写入到一个零食文件,全部写入完毕后,再rename该临时文件为磁盘文件的原名称,覆盖原文件。
- 如果再rewrite过程中又有写操作命令追加,那么这些数据会暂时写入aof_rewrite_buf缓冲区。等将全部rewrite计算结果写入临时文件后,会先将aof_rewrite_buf缓冲区中的数据写入临时文件,然后再rename为磁盘文件的原名称,覆盖原文件。
RDB与AOF对比
- RDB
- rdb文件较小,数据恢复快
- 数据安全性较差,写时复制会降低性能,rdb文件可读性差
- AOF
- 数据安全性高,可读性强
- aof文件较大,写操作会影响性能,数据恢复较慢
官方推荐使用RDB与AOF混合式持久化,若对数据安全性不高,则推荐使用纯RDB持久化方式。不推荐使用纯AOF持久化方式。若只是用于缓存,则无需使用持久化