在运行情况下,Redis 以数据结构的形式将数据维持在内存中,为了让这些数据在 Redis 重启之后仍然可用,需要将数据写入持久存储
持久化是指将数据写入持久存储,例如固态磁盘(SSD)
Redis 提供了一系列持久化选项。这些包括:
RDB(Redis Database)
:RDB 持久化以指定的时间间隔执行数据集的时间点快照。AOF(Append Only File)
:AOF 持久化记录服务器收到的每一个写操作。然后可以在服务器启动时再次重放这些操作,重建原始数据集。使用与 Redis 协议本身相同的格式记录命令。RDB + AOF
:RDB和AOF混合方式(4.0版本)
RDB和AOF的优缺点详见Redis持久化
RDB
RDB(Redis DataBase) ,意为快照/内存快照,RDB持久化是把当前进程数据生成快照保存到磁盘上的过程
由于是某一时刻的快照,那么快照中的值要早于或者等于内存中的值
RDB 功能最核心的是rdbSave
和rdbLoad
两个函数, 前者用于生成 RDB 文件到磁盘, 而后者则用于将 RDB 文件中的数据重新载入到内存中
RDB触发方式
触发rdb持久化的方式有2种,分别是手动触发和自动触发
手动触发
手动触发分别对应
SAVE
和BGSAVE
命令。
SAVE
命令直接调用rdbSave,阻塞Redis主进程BGSAVE
用子进程调用rdbSave,主进程仍可继续处理命令请求
为了避免产生竞争条件,
BGSAVE
执行时,SAVE
命令不能执行
- redis客户端执行bgsave命令或者自动触发bgsave命令
- 主进程判断当前是否已经存在正在执行的子进程,如果存在,那么主进程直接返回
- 如果不存在正在执行的子进程,那么就fork一个新的子进程进行持久化数据,fork过程是阻塞的,fork操作完成后主进程即可执行其他操作
- 子进程先将数据写入到临时的rdb文件中,待快照数据写入完成后再原子替换旧的rdb文件
- 同时发送信号给主进程,通知主进程rdb持久化完成,主进程更新相关的统计信息(info Persitence下的rdb_*相关选项)
自动触发
- redis.conf中配置
save m n
,即在m秒内有n次修改时,自动触发bgsave生成rdb文件 - 主从复制时,从节点要从主节点进行全量复制时也会触发bgsave操作,生成当时的快照发送到从节点
- 执行debug reload命令重新加载redis时也会触发bgsave操作
- 默认情况下执行shutdown命令时,如果没有开启aof持久化,那么也会触发bgsave操作
redis.conf中配置RDB快照周期:内存快照虽然可以通过技术人员手动执行SAVE或BGSAVE命令来进行,但生产环境下多数情况都会设置其周期性执行条件。
# 周期性执行条件的设置格式为
save <seconds> <changes>
# 默认的设置为:
# 如果900秒内有1条Key信息发生变化,则进行快照
save 900 1
# 如果300秒内有10条Key信息发生变化,则进行快照
save 300 10
# 如果60秒内有10000条Key信息发生变化,则进行快照
save 60 10000
# 以下设置方式为关闭RDB快照功能
save ""
RDB文件结构
此段文章修改自Redis 设计与实现,详细见原文
RDB 文件可以分为以下几个部分:
+-------+-------------+-----------+-----------------+-----+-----------+
| REDIS | RDB-VERSION | SELECT-DB | KEY-VALUE-PAIRS | EOF | CHECK-SUM |
+-------+-------------+-----------+-----------------+-----+-----------+
|<-------- DB-DATA ---------->|
REDIS
:文件的最开头保存着 REDIS 五个字符,标识着一个 RDB 文件的开始RDB-VERSION
:一个四字节长的以字符表示的整数,记录了该文件所使用的 RDB 版本号DB-DATA
:这个部分在一个 RDB 文件中会出现任意多次,每个 DB-DATA 部分保存着服务器上一个非空数据库的所有数据SELECT-DB
:这域保存着跟在后面的键值对所属的数据库号码KEY-VALUE-PAIRS
:因为空的数据库不会被保存到 RDB 文件,所以这个部分至少会包含一个键值对的数据EOF
:标志着数据库内容的结尾(不是文件的结尾),值为rdb.h/EDIS_RDB_OPCODE_EOF
(255)CHECK-SUM
:RDB 文件所有内容的校验和, 一个uint_64t
类型值
KEY-VALUE-PAIRS
每个键值对的数据使用以下结构来保存:
+----------------------+---------------+-----+-------+
| OPTIONAL-EXPIRE-TIME | TYPE-OF-VALUE | KEY | VALUE |
+----------------------+---------------+-----+-------+
OPTIONAL-EXPIRE-TIME
域是可选的,如果键没有设置过期时间,那么这个域就不会出现;反之,如果这个域出现的话,那么它记录着键的过期时间,在当前版本的 RDB中,过期时间是一个以毫秒为单位的 UNIX 时间戳。KEY
域保存着键,格式和 REDIS_ENCODING_RAW 编码的字符串对象一样(见下文)。TYPE-OF-VALUE
域记录着VALUE
域的值所使用的编码,根据这个域的指示,程序会使用不同的方式来保存和读取VALUE
的值
RDB优缺点
- 优点
- RDB文件是某个时间节点的快照,默认使用LZF算法进行压缩,压缩后的文件体积远远小于内存大小,适用于备份、全量复制等场景
- Redis加载RDB文件恢复数据要远远快于AOF方式
- 缺点
- RDB方式实时性不够,无法做到秒级的持久化
- 每次调用bgsave都需要fork子进程,fork子进程属于重量级操作,频繁执行成本较高
- RDB文件是二进制的,没有可读性,AOF文件在了解其结构的情况下可以手动修改或者补全
- 版本兼容RDB文件问题
针对RDB不适合实时持久化的问题,Redis提供了AOF持久化方式来解决
参考资料: