【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 仅用于缓存,则无需使用任何持久化技术

相关推荐
新手小袁_J17 分钟前
JDK11下载安装和配置超详细过程
java·spring cloud·jdk·maven·mybatis·jdk11
呆呆小雅17 分钟前
C#关键字volatile
java·redis·c#
miss writer1 小时前
Redis分布式锁释放锁是否必须用lua脚本?
redis·分布式·lua
亽仒凣凣2 小时前
Windows安装Redis图文教程
数据库·windows·redis
希忘auto3 小时前
详解Redis的常用命令
redis·1024程序员节
xlsw_10 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
岁月变迁呀10 小时前
Redis梳理
数据库·redis·缓存
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭11 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
Code apprenticeship12 小时前
怎么利用Redis实现延时队列?
数据库·redis·缓存
百度智能云技术站12 小时前
广告投放系统成本降低 70%+,基于 Redis 容量型数据库 PegaDB 的方案设计和业务实践
数据库·redis·oracle