【Redis】Redis持久化

Redis 是一个内存数据库,所以其运行效率非常高。但内存中的数据是不持久的,若主机宕机或 Redis 关机重启,则内存中的数据全部丢失。这是不允许的。Redis 具有持久化功能,其会按照设置以快照或操作日志的形式将数据持久化到磁盘。 根据持久化使用技术的不同,Redis 的持久化分为两种:RDB 与 AOF

1.基本原理

Redis 持久化的基本原理就是钝化与激活的过程

Redis 持久化也称为钝化,是指将内存中数据库的状态描述信息保存到磁盘中。只不过是不同的持久化技术,对数据的状态描述信息是不同的,生成的持久化文件也是不同的。但作用都是相同的:避免数据意外丢失

通过手动方式,或自动定时方式,或自动条件触发方式,将内存中数据库的状态描述信 息写入到指定的持久化文件中。当系统重新启动时,自动加载持久化文件,并根据文件中数 据库状态描述信息将数据恢复到内存中,这个数据恢复过程也称为激活

对于 Redis 单机状态下,无论是手动方式,还是定时方式或条件 触发方式,都存在数据丢失问题:在尚未手动/自动保存时发生了 Redis 宕机状况,那么从上 次保存到宕机期间产生的数据就会丢失。不同的持久化方式,其数据的丢失率也不同。RDB 是默认持久化方式,但 Redis 允许 RDB 与 AOF 两种持久化技术同时开启,AOF 持久化技术的优先级更高,因此系统会先使用 AOF 方式做持久化

2.RDB 持久化

指将内存中某一时刻的数据快照全量写入到指定的 RDB 文件的 持久化技术。RDB 持久化默认是开启的。当 Redis 启动时会自动读取 RDB 快照文件,将数据从硬盘载入到内存,以恢复关机前的数据库状态

2.1.持久化的执行

执行有三种方式:手动 save 命令、手动 bgsave 命令,与自动条件触发

1)手动 save 命令:客户端中执行 save 命令可立即进行一次持久化保存,在执行期 间会阻塞 redis-server 进程,直至持久化过程完毕,而在进程阻塞期间,Redis 不能处理任何读写请求,无法对外提供服务

2)手动 bgsave 命令:客户端中执行 bgsave 命令可立即进行一次持久化保存,在后台运行 save,会使服务器 进程 redis-server 生成一个子进程,由该子进程负责完成保存过程。在子进程进行保存过程 中,不会阻塞 redis-server 进程对客户端读写请求的处理

3)自动条件触发:本质是 bgsave 命令的执行,只不过是用户通过在配置文件中做相应的设置后,Redis 会根据设置信息自动调用 bgsave 命令执行

4)查看持久化时间:通过 lastsave 命令可以查看最近一次执行持久化的时间

2.2.优化配置

RDB 相关的配置在 redis.conf 文件的 SNAPSHOTTING 部分

1)save :该配置用于设置快照的自动保存触发条件,该触发条件是在指 定时间段内发生了指定次数的写操作,如果不启用 RDB 持久化,只需设置 save 的参数为空串即可:save ""

2)stop-write-on-bgsave-error:默认情况下,如果 RDB 快照已启用(至少一个保存点),且最近的 bgsave 命令失败,Redis 将停止接受写入。这样是为了让用户意识到数据没有正确地保存到磁盘上。如果 bgsave 命令后来可以正常工作了,Redis 将自动允许再次写入

3)rdbcompression:当进行持久化时启用 LZF 压缩字符串对象。虽然压缩 RDB 文件会消耗系统资源,降低性能,但可大幅降低文件的大小,方便保存到磁盘,加速主从集群中从节点的数据同步

4)rdbchecksum:从 RDB5 开始,RDB 文件的 CRC64 校验和就被放置在了文件末尾。这使格式更能抵抗 RDB 文件的损坏,但在保存和加载 RDB 文件时,性能会受到影响(约 10%),因此可以设置为 no 禁用校验和以获得最大性能。在禁用校验和的情况下创建的 RDB 文件的校验和为零,这将让加载代码跳过校验检查。默认为 yes,开启了校验功能

5)sanitize-dump-payload:用于设置在加载 RDB 文件或进行持久化时是否开启对 zipList、listPack 等数据的 全面安全检测。该检测可以降低命令处理时发生系统崩溃的可能。no:不检测;yes:总是检测;clients:只有当客户端连接时检测。排除了加载 RDB 文件与进行持久化时的检测

6)dbfilename:指定 RDB 文件的默认名称,默认为 dump.rdb

7)rdb-del-sync-files:主从复制时,是否删除用于同步的从机上的 RDB 文件。默认是 no,不删除。只有当从机的 RDB 和 AOF 持久化功能都未开启时才生效

8)dir:指定 RDB 与 AOF 文件的生成目录。默认为 Redis 安装根目录

2.3.文件结构

1)SOF:是一个常量,用于标识 RDB 文件的开始,以便在加载 RDB 文件时可以迅速判断出文件是否是 RDB 文件。如一个字符串 HI ,仅有两个字符,长度为2

2)rdb_version:一个整数,长度为 4 字节,表示 RDB 文件的版本号

3)EOF:一个常量,占 1 个字节,用于标识 RDB 数据的结束,校验和的开始

4)check_sum:校验和 check_sum 用于判断 RDB 文件中的内容是否出现数据异常。其采用的是 CRC 校验算法(数据损坏校验,而不是数据没有损坏的校验)

5)databases:是 RDB 文件中最重要的数据部分,其可以包含任意多个非空数据库。

SODB:是一个常量,占 1 个字节,用于标识一个数据库的开始

db_number:数据库编号;key_value_pairs:当前数据库中的键值对数据

每个key_value_pairs 又由很多个用于描述键值对的数据构成:

VALUE_TYPE:一个常量,占 1 个字节,标识该键值对中 value 的类型

EXPIRETIME_UNIT:是一个常量,占 1 个字节,用于标识过期时间的单位是秒还是毫秒

time:当前 key-value 的过期时间

2.4.持久化过程

在进行 bgsave 持久化时,redis-server 进程会 fork 出一 个 bgsave 子进程,由该子进程以异步方式负责完成持久化。而在持久化过程中,redis-server 进程不会阻塞,其会继续接收并处理用户的读写请求

bgsave 子进程:子进程可以继承父进程的所有资源,且父进程不能拒绝子进程的继承权。因此 bgsave 子进程有权读取到 redis-server 进程写入到内存中的用户数据,使得将内存数据持久化到 dump.rdb 成为可能。bgsave 子进程在持久化时首先会将内存中的全量数据 copy 到磁盘中的一个 RDB 临时文 件,copy 结束后,再将该文件 rename 为 dump.rdb,替换掉原来的同名文件。在进行持久化过程中,如果 redis-server 进程接收到了用户写请求,则系统会将内存中发生数据修改的物理块 copy 出一个副本。等内存中的全量数据 copy 结束后,会再将 副本中的数据 copy 到 RDB 临时文件。这个副本的生成是由于 Linux 系统的写时复制技术 (Copy-On-Write)实现的

3.AOF 持久化

指 Redis 将每一次的写操作都以日志的形式记录到一个 AOF 文件中的持久化技术。当需要恢复内存数据时,将这些写操作重新执行一次,便会恢复到之前的内存数据状态

3.1.基本配置

1)AOF 的开启:默认情况下没有开启,通过修改配置文件中的 appendonly 属性为 yes 开启

2)文件名配置:基本文件:可以是 RDB 格式也可以是 AOF 格式。其存放的内容是由 RDB 转为 AOF 当 时内存的快照数据。该文件可以有多个;增量文件:以操作日志形式记录转为 AOF 后的写入操作。该文件可以有多个;清单文件:用于维护 AOF 文件的创建顺序,保障激活时的应用顺序。该文件只有一个

3)混合式持久化开启:通过 aof-use-rdb-preamble 属性可以选择基本文件是 RDB 格式还是是 AOF 格式。其默认值为 yes,即默认 AOF 持久化的基本文件为 rdb 格式文件,默认采用混合式持久化

4)AOF 文件目录配置:为了方便管理,可以专门为 AOF 持久化文件指定存放目录。目录名由 appenddirname 属性指定,存放在 redis.conf 配置文件的 dir 属性指定的目录,默认为 Redis 安装目录

3.2.文件格式

AOF 文件包含三类文件:基本文件、增量文件与清单文件。基本文件一般为 rdb 格 式

3.3.Rewrite 机制

随着使用时间的推移,AOF 文件会越来越大。为了防止 AOF 文件由于太大而占用大量 的磁盘空间,降低性能,Redis 引入了 Rewrite 机制来对 AOF 文件进行压缩

3.4.优化配置

1)appendfsync:当客户端提交写操作命令后,该命令就会写入到 aof_buf 中,而 aof_buf 中的数据持久化到磁盘 AOF 文件的过程称为数据同步。有三种策略。

always:写操作命令写入 aof_buf 后会立即调用 fsync()系统函数,将其追加到 AOF 文件。 该策略效率较低,但相对比较安全,不会丢失太多数据。最多就是刚刚执行过的写操作 在尚未同步时出现宕机或重启,将这一操作丢失

no:写操作命令写入 aof_buf 后什么也不做,不会调用 fsync()函数。而将 aof_buf 中的 数据同步磁盘的操作由操作系统负责。Linux 系统默认同步周期为 30 秒。效率较高

everysec:默认策略。写操作命令写入 aof_buf 后并不直接调用 fsync(),而是每秒调用 一次 fsync()系统函数来完成同步。该策略兼顾到了性能与安全,是一种折中方案

2)no-appendfsync-on-rewrite:该属性用于指定,当 AOF fsync 策略设置为 always 或 everysec,当主进程创建了子进程 正在执行 bgsave 或 bgrewriteaof 时,主进程是否不调用 fsync()来做数据同步。设置为 no, 双重否定即肯定,主进程会调用 fsync()做同步。而 yes 则不会调用 fsync()做数据同步。如果调用 fsync(),在需要同步的数据量非常大时,会阻塞主进程对外提供服务,即会存 在延迟问题。如果不调用 fsync(),则 AOF fsync 策略相当于设置为了 no,可能会存在 30 秒 数据丢失的风险

3)aof-rewrite-incremental-fsync:当 bgrewriteaof 在执行过程也是先将 rewrite 计算的结果写入到了 aof_rewrite_buf 缓存中,然后当缓存中数据达到一定量后就会调用 fsync()进行刷盘操作,即数据同步,将数据写 入到临时文件。该属性用于控制 fsync()每次刷盘的数据量最大不超过 4MB。这样可以避免由 于单次刷盘量过大而引发长时间阻塞

4)aof-load-truncated:在进行 AOF 持久化过程中可能会出现系统突然宕机的情况,此时写入到 AOF 文件中的 最后一条数据可能会不完整。当主机启动后,Redis 在 AOF 文件不完整的情况下是否可以启 动,取决于属性 aof-load-truncated 的设置。yes:AOF 文件最后不完整的数据直接从 AOF 文件中截断删除,不影响 Redis 的启动;no:AOF 文件最后不完整的数据不可以被截断删除,Redis 无法启动

5)aof-timestamp-enabeld:属性设置为 yes 则会开启在 AOF 文件中增加时间戳的显示功能,可方便按照时间对数 据进行恢复。但该方式可能会与 AOF 解析器不兼容,所以默认值为 no,不开启

3.5.持久化过程

1)Redis 接收到的写操作命令并不是直接追加到磁盘的 AOF 文件的,而是将每一条写命令 按照 redis 通讯协议格式暂时添加到 AOF 缓冲区 aof_buf

2)根据设置的数据同步策略,当同步条件满足时,再将缓冲区中的数据一次性写入磁盘的 AOF 文件,以减少磁盘 IO 次数,提高性能

3)当磁盘的 AOF 文件大小达到了 rewrite 条件时,redis-server 主进程会 fork 出一个子进程 bgrewriteaof,由该子进程完成 rewrite 过程

5)子进程 bgrewriteaof 首先对该磁盘 AOF 文件进行 rewrite 计算,将计算结果写入到一个 临时文件,全部写入完毕后,再 rename 该临时文件为磁盘文件的原名称,覆盖原文件

5)如果在 rewrite 过程中又有写操作命令追加,那么这些数据会暂时写入 aof_rewrite_buf 缓冲区。等将全部 rewrite 计算结果写入临时文件后,会先将 aof_rewrite_buf 缓冲区中 的数据写入临时文件,然后再 rename 为磁盘文件的原名称,覆盖原文件

4.RDB 与 AOF 对比

4.1.RDB 优势与不足

1)优势:文件较小;数据恢复较快

2)不足:数据安全性较差;写时复制会降低性能;文件可读性较差

4.2.AOF 优势与不足

1)优势:数据安全性高;AOF 文件可读性强

2)不足:AOF 文件较大;写操作会影响性能;数据恢复较慢

5.持久化技术选择

官方推荐使用 RDB 与 AOF 混合式持久化,不推荐使用纯 AOF 持久化方式

对数据安全性要求不高,则推荐使用纯 RDB 持久化方式

若 Redis 仅用于缓存,则无需使用任何持久化技术

相关推荐
番茄炒鸡蛋加糖7 小时前
缓存三大问题
缓存
江晓鱼未暖12 小时前
十七、Redis 核心原理与架构详解
大数据·数据库·数据仓库·redis·缓存·架构
红莲凪是12 小时前
Redis有哪些部署方案?了解哨兵机制吗?
java·redis·eureka
小罗水12 小时前
第13章 Redis 缓存、幂等锁与任务状态
数据库·redis·缓存
热心市民lcj12 小时前
Spring Boot 整合 Caffeine 本地缓存实战
spring boot·后端·缓存
zx11545013 小时前
【热点 Key 探测与加长缓存 TTL 实战】
缓存
Devin~Y14 小时前
从本地生活电商到 AI RAG:互联网大厂 Java 面试场景完整实战
java·spring boot·redis·elasticsearch·spring cloud·kafka·rag
momo1 天前
Java+WebAI黑马知识点
java·spring boot·mybatis
toooooop81 天前
如何用 ss + ps 精准定位本机 Redis 的“隐形”消费者?
linux·数据库·redis·缓存
软萌萌的11 天前
C#中的多级缓存架构设计与实现深度解析
缓存·c#·wpf