Redis的持久化

目录

  • [1. 文章前言](#1. 文章前言)
  • [2. RDB](#2. RDB)
    • [2.1 触发机制](#2.1 触发机制)
    • [2.2 流程说明](#2.2 流程说明)
    • [2.3 RDB文件的处理](#2.3 RDB文件的处理)
    • [2.4 RDB的优缺点](#2.4 RDB的优缺点)
  • [3. AOF](#3. AOF)
    • [3.1 使用AOF](#3.1 使用AOF)
    • [3.2 命令写入](#3.2 命令写入)
    • [3.3 文件同步](#3.3 文件同步)
    • [3.4 重写机制](#3.4 重写机制)
    • [3.5 启动时数据恢复](#3.5 启动时数据恢复)
  • [4. 持久化总结](#4. 持久化总结)

1. 文章前言

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

  • 介绍RDB、AOF的配置和运行流程,以及控制持久化的命令,如bgsave和bgrewriteaof。
  • 对常见持久化问题进行分析定位和优化。

2. RDB

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

2.1 触发机制

(1)手动触发分别对应save和bgsave命令:

  • save命令:阻塞当前Redis服务器,直到RDB过程完成为止,对于内存比较大的实例造成长时间阻塞,基本不采用。
  • bgsave命令 :Redis 进程执行fork操作创建子进程, RDB持久化过程由子进程负责,完成后自动
    结束。阻塞只发生在fork阶段,一般时间很短。
    Redis内部的所有涉及RDB的操作都采用类似bgsave的方式。

(2)除了手动触发之外,Redis 运行自动触发RDB持久化机制,这个触发机制才是在实战中有价值的。

  1. 使用save配置。如"savemn"表示m秒内数据集发生了n次修改,自动RDB持久化。
  2. 从节点进行全量复制操作时,主节点自动进行RDB持久化,随后将RDB文件内容发送给从结点。
  3. 执行shutdown命令关闭Redis时,执行RDB持久化。

2.2 流程说明

(1)bgsave是主流的RDB持久化方式,下面根据图了解它的运作流程。bgsave命令的运作流程:

  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. 进程发送信号给父进程表示完成,父进程更新统计信息。

2.3 RDB文件的处理

(1)以下是RDB文件的处理过程:

  1. 保存:RDB 文件保存再dir配置指定的目录(默认/var/lib/redis/)下,文件名通过dbfilename配置(默认dump.rdb)指定。可以通过执行config set dir {newDir}和config set dbfilename{newFilename}运行期间动态执行,当下次运行时RDB文件会保存到新目录。
  2. 压缩:Redis 默认采用LZF算法对生成的RDB文件做压缩处理,压缩后的文件远远小于内存大小,默认开启,可以通过参数config set rdbcompression {yes|no}动态修改。虽然压缩RDB会消耗CPU,但可以大幅降低文件的体积,方便保存到硬盘或通过网络发送到从节点,因此建议开启。
  3. 校验:如果Redis启动时加载到损坏的RDB文件会拒绝启动。这时可以使用Redis提供的redis-check-dump工具检测RDB文件并获取对应的错误报告。

2.4 RDB的优缺点

  • RDB 是一个紧凑压缩的二进制文件,代表Redis在某个时间点上的数据快照。非常适用于备份,全量复制等场景。比如每6小时执行bgsave备份,并把RDB文件复制到远程机器或者文件系统中(如hdfs)用于灾备。
  • Redis加载RDB恢复数据远远快于AOF的方式。
  • RDB 方式数据没办法做到实时持久化 /秒级持久化。 因为bgsave 每次运行都要执行fork创建子进程,属于重量级操作,频繁执行成本过高。
  • RDB 文件使用特定二进制格式保存, Redis版本演进过程中有多个RDB版本,兼容性可能有风险

3. AOF

AOF (Append Only File)持久化 :以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中的命令达到恢复数据的目的。AOF的主要作用是解决了数据持久化的实时性,目前已经是Redis持久化的主流方式。理解掌握好AOF持久化机制对我们兼顾数据安全性和性能非常有帮助。

3.1 使用AOF

(1)开启AOF功能需要设置配置:appendonly yes默认不开启。AOF文件名通过appendfilename配置(默认是appendonly.aof)设置。保存目录同RDB持久化方式一致通过dir配置指定。

(2)AOF的工作流程操作 :命令写入(append) 、文件同步(sync) 、文件重写(rewrite)、重启加载(load) ,如下图所示。

  1. 所有的写入命令会追加到aof_buf (缓冲区)中。
  2. AOF缓冲区根据对应的策略向硬盘做同步操作。
  3. 随着AOF文件越来越大,需要定期对AOF文件进行重写,达到压缩的目的。
  4. 当Redis服务器启动时,可以加载AOF文件进行数据恢复。

3.2 命令写入

(1)AOF命令写入的内容直接是文本协议格式。例如set hello world这条命令,在AOF缓冲区会追加如下文本:

bash 复制代码
*3\r\n$3\r\nset\r\n$5\r\nhello\r\n$5\r\nworld\r\n 
  • 此处遵守Redis格式协议,Redis 选择文本协议可能的原因:文本协议具备较好的兼容性;实现简单;具备可读性。
  • AOF过程中为什么需要aof_buf 这个缓冲区? Redis 使用单线程响应命令,如果每次写AOF文件都直接同步硬盘,性能从内存的读写变成IO读写,必然会下降。先写入缓冲区可以有效减少IO次数,同时,Redis 还可以提供多种缓冲区同步策略,让用户根据自己的需求做出合理的平衡。

3.3 文件同步

(1)Redis提供了多种AOF缓冲区同步文件策略,由参数appendfsync控制,不同值的含义如下表所示。AOF缓冲区同步文件策略:

(2)系统调用write和fsync解析:

  • write操作会触发延迟写(delayed write)机制。Linux 在内核提供页缓冲区用来提供硬盘IO性能。write 操作在写入系统缓冲区后立即返回。同步硬盘操作依赖于系统调度机制,例如:缓冲区页空间写满或达到特定时间周期。同步文件之前,如果此时系统故障宕机,缓冲区内数据将丢失。
  • Fsync针对单个文件操作,做强制硬盘同步,fsync将阻塞直到数据写入到硬盘。
  • 配置为always时,每次写入都要同步AOF文件,性能很差,在一般的SATA硬盘上,只能支持大约几百TPS写入。除非是非常重要的数据,否则不建议配置。
  • 配置为no时,由于操作系统同步策略不可控,虽然提高了性能,但数据丢失风险大增,除非数据重要程度很低,一般不建议配置。
  • 配置为everysec, 是默认配置,也是推荐配置,兼顾了数据安全性和性能。理论上最多丢失1秒的数据。

3.4 重写机制

(1)随着命令不断写入AOF,文件会越来越大,为了解决这个问题,Redis 引入AOF重写机制压缩文件体积。AOF文件重写是把Redis进程内的数据转化为写命令同步到新的AOF文件。重写后的AOF为什么可以变小?有如下原因:

  • 进程内已超时的数据不再写入文件。
  • 旧的AOF中的无效命令,例如del、hdel、srem等重写后将会删除,只需要保留数据的最终版本。
  • 多条写操作合并为一条,例如lpush list a、lpush list b、lpush list c 可以合并为lpush list a b c。
  • 较小的AOF文件一方面降低了硬盘空间占用,一方面可以提升启动Redis时数据恢复的速度。

(2)AOF重写过程可以分为手动触发和自动触发:

  • 手动触发:调用bgrewriteaof命令。
  • 自动触发:根据auto-aof-rewrite-min-size和auto-aof-rewrite- percentage参数确定自动触发时机。
  • auto- aof-rewrite-min-size:表示触发重写时AOF的最小文件大小,默认为64MB。
  • auto-aof-rewrite-percentage:代表当前AOF占用大小相比较上次重写时增加的比例。

(3)当触发AOF重写时,下图介绍它的运行流程。AOF重写流程:

  1. 执行AOF重写请求。如果当前进程正在执行AOF重写,请求不执行。如果当前进程正在执行bgsave操作,重写命令延迟到bgsave完成之后再执行。
  2. 父进程执行fork创建子进程。
  3. 重写:
    • 主进程fork之后,继续响应其他命令。所有修改操作写入AOF缓冲区并根据appendfsync策略同步到硬盘,保证旧AOF文件机制正确。
    • 子进程只有fork之前的所有内存信息,父进程中需要将fork之后这段时间的修改操作写入AOF重写缓冲区中。
  4. 子进程根据内存快照,将命令合并到新的AOF文件中。
  5. 子进程完成重写:
    • 新文件写入后,子进程发送信号给父进程。
    • 父进程把AOF重写缓冲区内临时保存的命令追加到新AOF文件中。
    • 用新AOF文件替换老AOF文件。

3.5 启动时数据恢复

(1)当Redis启动时,会根据RDB和AOF文件的内容,进行数据恢复,如下图所示。Redis根据持久化文件进行数据恢复:

4. 持久化总结

  1. Redis 提供了两种持久化方案:RDB 和 AOF。
  2. RDB 视为内存的快照,产生的内容更为紧凑,占用空间较小,恢复时速度更快。但产生 RDB 的开销较大,不适合进行实时持久化,⼀般用于冷备和主从复制。
  3. AOF 视为对修改命令保存,在恢复时需要重放命令。并且有重写机制来定期压缩 AOF 文件。
  4. RDB 和 AOF 都使用 fork 创建子进程,利用 Linux 子进程拥有父进程内存快照的特点进行持久化,尽可能不影响主进程继续处理后续命令。
相关推荐
烂不烂问厨房19 分钟前
uniapp 发布后原生img正常,image无法显示,img与uniapp image使用区别
uni-app·github
一只搬砖的猹1 小时前
软件项目开发关键节点——开源合规扫描
测试工具·开源·github·apache·license·软件项目·开源合规
Cikiss3 小时前
图解Git——分支开发工作流《Pro Git》
git·后端·源代码管理
梓羽玩Python4 小时前
推荐一款AI虚拟试衣神器!逼真的试穿效果,数据兼容性强!
github
阿雄不会写代码8 小时前
如何在后端使用redis进行缓存,任意一种语言都可以
redis·缓存·bootstrap
SafePloy安策12 小时前
商用服务器密码机的加密技术与优势
运维·服务器·github
学会沉淀。17 小时前
Redis
数据库·redis·缓存
半路程序员21 小时前
Git学习记录
git·学习
Cikiss1 天前
图解Git——分支的新建与合并《Pro Git》
git
班乃1 天前
Git提交失败【File[xxxxxx] size xxxMB, exceeds quota 100MB】
git