跳至主要內容

Redis进阶-持久化机制

Zenghr大约 8 分钟

Redis 持久化机制

Redis是一个支持持久化的内存数据库,也就是说 redis 需要经常将内存中的数据同步到硬盘来保证持久化

Redis持久化主要分为两种方式,分别是RDB和AOF,当然实际场景下还会使用这两种的混合模式

前言

Redis的数据正常都是存储在内存内,如果宕机突然发生,数据就会全部丢失,因此需要提供一种方式保证 redis 的数据不会因为故障而丢失,这种机制就是 redis 的持久化机制

目前 Redis 主流的持久化机制有两种:RDB 方式 和 AOF 方式

RDB 持久化

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

手动触发

手动触发分别对应 save 和 bgsave 命令

  • save命令:阻塞当前Redis服务器,直到RDB过程完成为止,对于内存 比较大的实例会造成长时间阻塞,线上环境不建议使用
  • bgsave命令:Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短

bgsave 命令是针对 save 阻塞问题做的优化,因此Redis内部所有涉及到RDB操作都采用 bgsave 的方式,而 save 命令可以废弃

bgsave流程图如下所示👇

eFa8oF
eFa8oF

具体流程如下:

  • redis 客户端执行 bgsave 命令或者自动触发bgsave命令;
  • 主进程判断当前是否已经存在正在执行的子进程,如果存在,那么主进程直接返回;
  • 如果不存在正在执行的子进程,那么就fork一个新的子进程进行持久化数据,fork过程是阻塞的,fork操作完成后主进程即可执行其他操作;
  • 子进程先将数据写入到临时的rdb文件中,待快照数据写入完成后再原子替换旧的rdb文件;
  • 同时发送信号给主进程,通知主进程rdb持久化完成,主进程更新相关的统计信息(info Persitence下的rdb_*相关选项)

自动触发

在以下4种情况时会自动触发

  • redis.conf中配置save m n,即在m秒内有n次修改时,自动触发bgsave生成rdb文件;

  • 主从复制时,从节点要从主节点进行全量复制时也会触发bgsave操作,生成当时的快照发送到从节点;

  • 执行 debug reload 命令重新加载 redis 时也会触发bgsave操作;

  • 默认情况下执行shutdown命令时,如果没有开启 aof持久化,那么也会触发bgsave操作

redis.conf中配置RDB

  • 配置设置自动做快照持久化方式
# 周期性执行条件的设置格式为
save <seconds> <changes>

# 默认的设置为:
save 900 1
save 300 10
save 60 10000

# 以下设置方式为关闭RDB快照功能
save ""

以上三项默认信息设置代表的意义是:

  • 如果900秒内有1条Key信息发生变化,则进行快照;
  • 如果300秒内有10条Key信息发生变化,则进行快照;
  • 如果60秒内有10000条Key信息发生变化,则进行快照。读者可以按照这个规则,根据自己的实际请求压力进行设置调整
# 文件名称
dbfilename dump.rdb
# 文件保存路径
dir /home/work/app/redis/data/
# 如果持久化出错,主进程是否停止写入
stop-writes-on-bgsave-error yes
# 是否压缩
rdbcompression yes
# 导入时是否检查
rdbchecksum yes
  • dbfilename: 配置文件名,可以通过执行 config set dir {newDir}config set dbfilename {newFileName} 运行期动态执行,当下次运行时RDB文件会保存到新目录

  • dir: 可以通过执行 config set dir {newDir}config set dbfilename {newFileName} 运行期动态执行,当下次运行时RDB文件会保存到新目录

  • 压缩: Redis默认采用 LZF算法 对生成的RDB文件做压缩处理,压缩后的文件远远小于内存大小,默认开启,可以通过参数 config set rdbcompression {yes|no} 动态修改。

  • 校验: 如果Redis加载损坏的RDB文件时拒绝启动,这个功能大概会多损失10%左右的性能,但获得了更高的数据可靠性。所以如果您的Redis服务需要追求极致的性能,就可以将这个选项设置为 no

RDB 的优缺点

  • 优点:

    • RDB文件是某个时间节点的快照,默认使用LZF算法进行压缩,压缩后的文件体积远远小于内存大小,适用于备份、全量复制等场景
    • Redis加载RDB文件恢复数据要远远快于AOF方式
  • 缺点:

    • RDB方式实时性不够,无法做到秒级的持久化;
    • 每次调用bgsave都需要fork子进程,fork子进程属于重量级操作,频繁执行成本较高;
    • RDB文件是二进制的,没有可读性,AOF文件在了解其结构的情况下可以手动修改或者补全;
    • 版本兼容RDB文件问题

    针对RDB不适合实时持久化的问题,Redis提供了 AOF持久化 方式来解决

AOF 持久化

AOF(append only file)持久化:以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中命令达到恢复数据的目的。

AOF的主要作用是解决了数据持久化的实时性,目前已经是 Redis持久化的主流方式

而AOF日志采用写后日志,即 先写内存,后写日志

a20AVK
a20AVK

Redis要求高性能,采用写日志有两方面好处:

  • 避免额外的检查开销:Redis 在向 AOF 里面记录日志的时候,并不会先去对这些命令进行语法检查。所以,如果先记日志再执行命令的话,日志中就有可能记录了错误的命令,Redis 在使用日志恢复数据时,就可能会出错。
  • 不会阻塞当前的写操作

但这种方式存在潜在风险:

  • 如果命令执行完成,写日志之前宕机了,会丢失数据。
  • 主线程写磁盘压力大,导致写盘慢,阻塞后续操作

如何实现 AOF

AOF日志记录Redis的每个写命令,步骤分为:命令追加(append)、文件写入(write)和文件同步(sync)

  • 命令追加 当AOF持久化功能打开了,服务器在执行完一个写命令之后,会以协议格式将被执行的写命令追加到服务器的 aof_buf 缓冲区。

  • 文件写入和同步 关于何时将 aof_buf 缓冲区的内容写入AOF文件中,Redis提供了三种写回策略

LATaFC
LATaFC
  • Always - 同步写回:每个写命令执行完,立马同步地将日志写回磁盘
  • Everysec(推荐) - 每秒写回:每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区,每隔一秒把缓冲区中的内容写入磁盘
  • No - 操作系统控制的写回:每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘(不推荐)

Conf 配置AOF

默认情况下,Redis是没有开启AOF的,可以通过配置redis.conf文件来开启AOF持久化,关于AOF的配置如下:

# appendonly参数开启AOF持久化
appendonly no

# AOF持久化的文件名,默认是appendonly.aof
appendfilename "appendonly.aof"

# AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数设置的
dir ./

# 同步策略
# appendfsync always
appendfsync everysec
# appendfsync no

# aof重写期间是否同步
no-appendfsync-on-rewrite no

# 重写触发配置
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

# 加载aof出错如何处理
aof-load-truncated yes

# 文件重写策略
aof-rewrite-incremental-fsync yes

以下是Redis中关于AOF的主要配置信息:

  • appendonly:默认情况下AOF功能是关闭的,将该选项改为yes以便打开Redis的AOF功能。

  • appendfilename:这个参数项很好理解了,就是AOF文件的名字

  • appendfsync:这个参数项是AOF功能最重要的设置项之一,主要用于设置操作命令向AOF文件中同步的策略

RDB和AOF混合方式

Redis 4.0 中提出了一个混合使用 AOF 日志和内存快照的方法。简单来说,内存快照以一定的频率执行,在两次快照之间,使用 AOF 日志记录这期间的所有命令操作

这样一来,快照不用很频繁地执行,这就避免了频繁 fork 对主线程的影响。而且,AOF 日志也只用记录两次快照间的操作,也就是说,不需要记录所有操作了,因此,就不会出现文件过大的情况了,也可以避免重写开销。

如下图所示,T1 和 T2 时刻的修改,用 AOF 日志记录,等到第二次做全量快照时,就可以清空 AOF 日志,因为此时的修改都已经记录到快照中了,恢复时就不再用日志了

yBKz08
yBKz08

这个方法既能享受到 RDB 文件快速恢复的好处,又能享受到 AOF 只记录操作命令的简单优势, 实际环境中用的很多

参考文档