侧边栏壁纸
博主昵称
流苏小筑

步伐虽小,密而不止

Redis持久化

2023年05月06日 19阅读 0评论 0点赞

Redis持久化(RDB&AOF)

RDB(RedisDB)

在指定的时间间隔内,将内存中的数据集快照写入到磁盘中,也就是snapshot,它恢复数据时就是将快照文件直接读取到内存

触发机制

1.手动触发

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

2.自动触发

而自动触发的场景主要是有以下几点:

  • 根据我们的 save m n 配置规则自动触发;
#900秒内,至少有一个key进行了修改,就进行持久化操作
save 900 1
#300秒内,至少有10个key进行了修改,就进行持久化操作
save 300 10
#60秒内,至少有1000个key进行了修改,就进行持久化操作
save 60 10000
  • 从节点全量复制时,主节点发送rdb文件给从节点完成复制操作,主节点会触发 bgsave
  • 执行 debug reload 时;
  • 执行 shutdown时,如果没有开启aof,也会触发。

同步流程:

由于 <font style="color:rgb(255, 80, 44);background-color:rgb(255, 245, 245);">save</font> 基本不会被使用到,我们重点看看 <font style="color:rgb(255, 80, 44);background-color:rgb(255, 245, 245);">bgsave</font> 这个命令是如何完成RDB的持久化的。

  1. 执行bgsave命令,Redis父进程判断当前是否存在正在执行的子进程,如RDB/AOF子进程,如果存在bgsave命令直接返回。
  2. 父进程执行fork操作创建子进程,fork操作过程中父进程会阻塞,通过info stats命令查看latest_fork_usec选项,可以获取最近一个fork操作的耗时,单位为微秒。
  3. 父进程fork完成后,bgsave命令返回“Background saving started”信息并不再阻塞父进程,可以继续响应其他命令。
  4. 子进程创建RDB文件,根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换。执行lastsave命令可以获取最后一次生成RDB的时间,对应info统计的rdb_last_save_time选项。
  5. 进程发送信号给父进程表示完成,父进程更新统计信息。

m4gwyk7s.png

Redis配置文件

Redis常用配置:
# 默认情况下Redis将自动保存数据:
# 3600  秒(1 小时)后,如果至少更改了  1  个键
# 300   秒(5 分钟)后,如果至少更改了 100 个键
# 60    秒(1 分钟)后,如果至少更改了10000个键
# 您可以通过取消注释以下三行来显式设置这些(可自定义save 秒 键)
save 3600 1
save 300 100
save 60 10000

# 当bgsave出现错误时,Redis是否停止执行写命令;
#   yes:则当硬盘出现问题时,可以及时发现,避免数据的大量丢失;
#   no:则Redis无视bgsave的错误继续执行写命令,当对Redis服务器的系统(尤其是硬盘)使用了监控时,该选项考虑设置为no
stop-writes-on-bgsave-error yes

# 是否开启RDB文件压缩
rdbcompression yes

# 是否开启RDB文件的校验,在写入文件和读取文件时都起作用;关闭checksum在写入文件和启动文件时大约能带来10%的性能提升,
# 但是数据损坏时无法发现
rdbchecksum yes

# 存储后的RDB文件名 默认dump.rdb
dbfilename dump.rdb

# 是否删除主从复制时创建的RDB文件(在没有开启持久化的实例中,最好将其删除)
rdb-del-sync-files no

# 存储持久化文件的目录 以上使用“dbfilename”配置指令,附加文件也将在此目录中创建
dir ./

AOF

默认都是自动触发RDB持久化方式的,若想AOF持久化方式我们首先得去配置文件开启此功能;appendonly yes 默认是未开启;而AOF持久化的文件名则需要通过 appendfilename 来配置,默认AOF文件名称为appendonly.aof;保存路径同RDB持久化方式一致,通过dir配置指定。

AOF的执行方式

只要执行增删改命令就会执行一次追加操作,往 appendonly.aof 文件内追加增删改命令。

流程

①:所有的增删改命令会追加到aof_buf(AOF缓冲区)中。

②:根据不同的同步策略将aof_buf中的内容同步到硬盘。

③:随着AOF文件越来越大,需要定期对AOF文件进行重写,达到压缩的目的。

④:当Redis服务器重启时,可以加载AOF文件进行数据恢复。

m4gwyuhz.png

AOF命令追加方式(append):

  • Redis先将写命令追加到缓冲区,而不是直接写入文件,主要是为了避免每次有写命令都直接写入硬盘,导致硬盘IO成为Redis负载的瓶颈
  • 命令追加的格式是Redis命令请求的协议格式,它是一种纯文本格式,具有兼容性好、可读性强、容易处理、操作简单避免二次开销等优点
  • 具体格式略。在AOF文件中,除了用于指定数据库的select命令(如select 0 为选中0号数据库)是由Redis添加的,其他都是客户端发送来的写命令。

AOF持久化策略的配置(appendfsync属性说明)

  • always:

    • 写入aof_buf后立即调用系统fsync操作同步到AOF文件,fsync完成后线程返回。
    • 这种情况下,每次增删改命令都要同步到AOF文件,这硬盘IO会成为性能瓶颈,Redis只能支持大约几百TPS写入,严重降低了Redis的性能;即便是使用固态硬盘(SSD),每秒大约也只能处理几万个命令,而且会大大降低SSD的寿命。
    • 总结:每次增删改都执行fsync,以保证数据同步到磁盘,安全性高,但性能较差
  • no:

    • 写入aof_buf后调用系统write操作,不对AOF文件做fsync同步;同步由操作系统负责,通常同步周期为30秒。
    • 这种情况下,文件同步的时间不可控,且缓冲区中堆积的数据会很多,数据安全性无法保证。
    • 总结:由操作系统保证数据同步到磁盘,Linux的默认fsync策略是30秒,最多会丢失30s的数
  • everysec:

    • 写入aof_buf后调用系统write操作,write完成后线程返回;fsync同步文件操作由专门的线程每秒调用一次。
    • everysec是前述两种策略的折中,是性能和数据安全性的平衡,因此是Redis的默认配置,也是我们推荐的配置。

AOF文件重写(rewrite)

随着时间流逝,Redis服务器执行的写命令越来越多,AOF文件也会越来越大;过大的AOF文件不仅会影响服务器的正常运行,也会导致数据恢复需要的时间过长。

文件重写:

是指定期重写AOF文件,减小AOF文件的体积。需要注意的是,AOF重写是把Redis进程内的数据转化为写命令,同步到新的AOF文件;不会对旧的AOF文件进行任何读取、写入操作!

关于文件重写需要注意的另一点是:

对于AOF持久化来说,文件重写虽然是强烈推荐的,但并不是必须的;即使没有文件重写,数据也可以被持久化并在Redis启动的时候导入;因此在一些实现中,会关闭自动的文件重写,然后通过定时任务在每天的某一时刻定时执行。

文件重写之所以能够压缩AOF文件,原因在于:

  1. 过期的数据不再写入文件
  2. 无效的命令不再写入文件:如有些数据被重复设值(set name jack, set name tom)、有些数据被删除了(sadd myset v1, del myset)等等
  3. 多条命令可以合并为一个:如sadd myset v1, sadd myset v2, sadd myset v3可以合并为sadd myset v1 v2 v3,不过为了防止单条命令过大造成客户端缓冲区溢出,对于list、set、hash、zset类型的key,并不一定只使用一条命令;而是以某个常量为界将命令拆分为多条。这个常量在redis.h/REDIS_AOF_REWRITE_ITEMS_PER_CMD中定义,不可更改,3.0版本中值是64。

通过上述内容可以看出,由于重写后AOF执行的命令减少了,文件重写既可以减少文件占用的空间,也可以加快恢复速度。

文件重写触发方式:

  • 手动触发

    • 直接调用bgrewriteaof命令,该命令的执行与bgsave有些类似,都是fork子进程进行具体工作,且都只有在fork时阻塞
  • 自动触发

    • 自动触发是根据auto-aof-rewrite-min-sizeauto-aof-rewrite-percentage配置参数,以及aof_current_size和aof_base_size状态确定触发时机

m4gwz3ty.png

AOF配置文件

# 是否开启AOF日志记录,默认redis使用的是rdb方式持久化,这种方式在许多应用中已经足够用了,但是redis如果中途宕机,
# 会导致可能有几分钟的数据丢失(取决于dump数据的间隔时间),根据save来策略进行持久化,
# Append Only File是另一种持久化方式, 可以提供更好的持久化特性,Redis会把每次写入的数据在接收后都写入
# appendonly.aof文件,每次启动时Redis都会先把这个文件的数据读入内存里,先忽略RDB文件。默认不启用此功能
appendonly yes

# 文本文件AOF的文件名,存放目录在dir配置中配置
appendfilename "appendonly.aof"

# aof持久化策略的配置(appendfsync属性说明)
# always:
#   命令写入aof_buf后立即调用系统fsync操作同步到AOF文件,fsync完成后线程返回。这种情况下,每次增删改命令都要同步到AOF文件,
#   这硬盘IO会成为性能瓶颈,Redis只能支持大约几百TPS写入,严重降低了Redis的性能;即便是使用固态硬盘(SSD),每秒大约也只能
#   处理几万个命令,而且会大大降低SSD的寿命。
#   总结:每次增删改都执行fsync,以保证数据同步到磁盘,安全性高,但性能较差
# no:
#   命令写入aof_buf后调用系统write操作,不对AOF文件做fsync同步;同步由操作系统负责,通常同步周期为30秒。这种情况下,
#   文件同步的时间不可控,且缓冲区中堆积的数据会很多,数据安全性无法保证。
#   总结:由操作系统保证数据同步到磁盘,Linux的默认fsync策略是30秒,最多会丢失30s的数据
# everysec:
#   命令写入aof_buf后调用系统write操作,write完成后线程返回;fsync同步文件操作由专门的线程每秒调用一次。
#   everysec是前述两种策略的折中,是性能和数据安全性的平衡,因此是Redis的默认配置,也是我们推荐的配置。
# appendfsync always
appendfsync everysec
# appendfsync no

# 在AOF rewrite期间,是否对aof新记录的append暂缓使用文件同步策略,主要考虑磁盘IO开支和请求阻塞时间
# no:
#   表示"不暂缓",新的aof记录仍然会被立即同步到磁盘,是最安全的方式,不会丢失数据,但是要忍受阻塞的问题
# yes:
#   相当于将appendfsync设置为no,这说明并没有执行磁盘操作,只是写入了缓冲区,因此这样并不
#   会造成阻塞(因为没有竞争磁盘),但是如果这个时候redis挂掉,就会丢失数据。丢失多少数据呢?Linux
#   的默认fsync策略是30秒,最多会丢失30s的数据,但由于yes性能较好而且会避免出现阻塞因此比较推荐rewrite
#   即对aof文件进行整理,将空闲空间回收,从而可以减少恢复数据时间
no-appendfsync-on-rewrite no
# aof_current_size 和 aof_base_size 可以执行 info persistence 或直接 info
# 执行AOF重写时,当前AOF大小(即aof_current_size)和上一次重写时AOF大小(aof_base_size)的比值;文件重写触发条件之一
auto-aof-rewrite-percentage 100
# 执行AOF重写时,文件的最小体积,默认值为64MB。文件重写触发条件之一
auto-aof-rewrite-min-size 64mb

# 是否加载由于某些原因导致的末尾异常的AOF文件(主进程被kill/断电等),建议yes
aof-load-truncated yes

# redis4.0新增RDB-AOF混合持久化格式,在开启了这个功能之后,AOF重写产生的文件将同时包含RDB格式的内容和AOF格式的内容,
# 其中RDB格式的内容用于记录已有的数据,而AOF格式的内容则用于记录最近发生了变化的数据,这样Redis就可以同时兼有RDB持
# 久化和AOF持久化的优点(既能够快速地生成重写文件,也能够在出现问题时,快速地载入数据),默认为no,即不启用此功能
aof-use-rdb-preamble yes

从持久化中恢复数据

数据的备份、持久化做完了,我们如何从这些持久化文件中恢复数据呢?如果一台服务器上有既有RDB文件,又有AOF文件,该加载谁呢?

其实想要从这些文件中恢复数据,只需要重新启动Redis即可。我们还是通过图来了解这个流程:

m4gwzegi.png

AOF和RDB优缺点

RDB持久化:

优点:RDB文件紧凑,体积小,网络传输快,适合全量复制;恢复速度比AOF快很多。当然,与AOF相比,RDB最重要的优点之一是对性能的影响相对较小。

缺点:RDB文件的致命缺点在于其数据快照的持久化方式决定了必然做不到实时持久化,而在数据越来越重要的今天,数据的大量丢失很多时候是无法接受的,因此AOF持久化成为主流。此外,RDB文件需要满足特定格式,兼容性差(如老版本的Redis不兼容新版本的RDB文件)。

AOF持久化:

与RDB持久化相对应,AOF的优点在于支持秒级持久化、兼容性好,缺点是文件大、恢复速度慢、对性能影响大。

RDB和AOF混合持久化

rdb和aof可以共存吗?

答:可以

rdb和aof同时开启,听谁的?

答:以aof为主。

m4gwzp1v.png

开启混合模式:aof-use-rdb-preamble yes

rdb:全量持久化

aof:增量持久化

关闭rdb和aof

  • 禁用RDB:save "" (仍可以使用save和bgsave手动生成rdb文件)
  • 禁用AOF:appendonly no (仍可以使用bgrewriteaof手动生成aof文件)
0

—— 评论区 ——

昵称
邮箱
网址
取消
博主栏壁纸
博主头像 流苏小筑

步伐虽小,密而不止

133 文章数
27 标签数
16 评论量