Redis的持久化(persistence)
Redis支持将内存中数据写入硬盘存储,防止数据丢失,持久化办法有三种,分别是RDB(Redis Database)、AOF(Append Only File)和RDB+AOF。
1. RDB方式
在指定的时间间隔,执行数据集的时间点全量快照📷,写入到磁盘中,其中快照文件就称为RDB文件(dump.rdb)
1.1 RDB配置参数说明
save <seconds> <changes> [<seconds <changes>...]
表示连续设置一个或多个m秒内数据集存在n次修改时,自动触发持久化。dbfilename
RDB快照文件的文件名dir
RDB快照文件保存的文件夹stop-writes-on-bgsave-error
默认yes,如果配置成no,表示你不在乎数据不一致或者有其他的手段发现和控制这种不一致,那么在快照写入失败时,也能确保redis继续接受新的写请求。rdbcompression
默认yes,对于存储到磁盘中的快照,可以设置是否进行压缩存储。如果是的话,redis会采用LZF算法进行压缩。如果你不想消耗CPU来进行压缩的话,可以设置为关闭此功能。rdbchecksum
默认yes, 在存储快照后,还可以让Redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能。rdb-del-sync-files
在没有持久性的情况下删除复制中使用的RDB文件启用。默认情况下no,此选项是禁用的。
1.2 自动RDB配置
- 配置redis.conf文件
- Redis6.0.16之前版本
修改SNAPSHOTTING节点save参数,来触发Redis自动持久化。
其中save的格式:save m n
表示m秒内数据集存在n次修改时,自动触发持久化,默认策略是: - Redis6.0.16之后版本
修改SNAPSHOTTING节点save参数,来触发Redis自动持久化。
默认策略是:save 3600 1 300 100 60 10000
每隔1小时,如果有超过1个key发生改变,就写一次新的RDB文件。
每隔5分钟,如果有超过100个key发生改变,就写一次新的RDB文件。
每隔1分钟,如果有超过10000个key发生改变,就写一次新的RDB文件。
- Redis6.0.16之前版本
1.3 手动设置RDB
Redis提供了两个命令来生成RDB文件,分别是save
和bgsave
- save命令
语法:SAVE
在主程序中执行会阻塞当前redis服务器,直到持久化工作完成执行save
命令期间,Redis不能处理其他命令,线上禁止使用 - bgsave命令
语法:BGSAVE [SCHEDULE]
Redis会在后台异步进行快照操作,不阻塞快照同时还可以响应客户端请求,该触发方式会fork一个子进程由子进程复制持久化过程。如果使用SCHEDULE
参数,表示当AOF重写正在进行时,该命令将立即返回OK,并安排在下一次机会时运行后台保存。
192.168.101.105:6379> BGSAVE
Background saving started
- lastsave命令
语法:LASTSAVE
返回最后一次保存RDB文件的UNIX时间戳, 可以用来监控查询BGSAVE
异步保存RDB文件是否完成。
192.168.101.105:6379> LASTSAVE
(integer) 1710049761
192.168.101.105:6379> bgsave
Background saving started
192.168.101.105:6379> lastsave
(integer) 1710057622
可以发现两次lastsave
命令返回时间戳不同,即可认为bgsave
已经执行完成。如需转换时间戳可以使用linux的data
命令,比如:
## 得到具体日期
[root@hadoop105 redis-7.2.4]# date -d @1710057622
2024年 03月 10日 星期日 16:00:22 CST
1.4 配置RDB文件位置
- 获取当前RDB文件位置
192.168.101.105:6379> config get dir
1) "dir"
2) "/opt/module/redis-7.2.4/bin"
- 修改RDB文件位置和文件名
[jack@hadoop105 redis-7.2.4]$ vi conf/redis.conf
# dir ./ 改为 dir /opt/module/redis-7.2.4/data/
# dbfilename dump.rdb 改为 dbfilename master6379.rdb
## 修改配置后重启redis
[root@hadoop105 redis-7.2.4]# ./bin/redis-server ./conf/redis.conf
## 远程连接redis查看配置
192.168.101.105:6379> config get dir
1) "dir"
2) "/opt/module/redis-7.2.4/data"
警告
flushdb
清空Redis,是不能恢复数据的,原因在于执行flushall
/flushdb
命令也会产生dump.rdb文件,但里面是空的, 已经失去备份恢复意义。- 不可以在生产上把备份文件dump.rdb和redis服务器放在同一台机器,必须分开各自存储,以防生产机物理损坏后备份文件也挂了。
1.5 RDB优缺点
- RDB优点
- RDB是Redis数据的一个非常紧凑的单文件快照。RDB文件非常适合备份。提供很自由的保存RDB快照的规则,这使您可以在发生灾难时轻松恢复不同版本的数据集。
- RDB非常适合灾难恢复,它是一个可以传输到远程数据中心或 Amazon S3(可能已加密)的压缩文件。
- RDB最大限度地提高了Redis的性能,因为Redis父进程为了持久化而派生一个子进程。父进程永远不会执行磁盘I0或类似操作。与AOF相比,RDB允许使用大数据集更快地重启。
- 在副本上,RDB 支持重启和故障转移后的部分重新同步
- RDB缺点
- 如果您需要在Redis停止工作时(例如断电后)将数据丢失的可能性降到最低,那么RDB并不好。配置生成RDB的不同保存时间点,而在这期间都可能Redis不正确的关闭而丢失最新的数据。
- RDB需要经常fork()以便使用子进程在磁盘上持久化。如果数据集很大,fork()也可能会很耗时,并且如果数据集很大并且CPU性能不是很好,可能会影响Redis为客户端服务几秒甚至一秒钟。
1.6 修复RDB文件
使用RDB文件检查工具redis-check-rdb可以处理常见的rdb问题。
[root@hadoop105 bin]# ./redis-check-rdb ../data/master6379.rdb
[offset 0] Checking RDB file ../data/master6379.rdb
[offset 26] AUX FIELD redis-ver = '7.2.4'
[offset 40] AUX FIELD redis-bits = '64'
[offset 52] AUX FIELD ctime = '1710057621'
[offset 67] AUX FIELD used-mem = '1283176'
[offset 79] AUX FIELD aof-base = '0'
[offset 81] Selecting DB ID 0
[offset 187] Checksum OK
[offset 187] \o/ RDB looks OK! \o/
[info] 4 keys read
[info] 0 expires
[info] 0 already expired
1.7 触发写入RDB文件条件
- 配置文件中默认的快照配置
- 手动
save
/bgsave
命令 - 执行
flushall/
flushdb`命令也会产生dump.rdb文件,但里面是空的,无意义 - 执行
shutdown
且没有设置开启AOF持久化 - 主从复制时,主节点自动触发
1.8 禁用RDB快照
- 动态修改停止RDB保存快照
使用config set save
命令, 将保存快照规则重置为空字符串即可,缺点是重启Redis后配置信息丢失。
192.168.101.105:6379> config set save ""
OK
- 修改redis.conf文件
## 新增一行
save ""
重启Redis服务器即可生效。
2. AOF方式
以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,Redis启动之初会读取该文件重新构建数据,换言之,Redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。
2.1 AOF工作流程
步骤 | 详情 |
---|---|
1 | Client作为命令的来源,会有多个源头以及源源不断的请求命令。 |
2 | 在这些命令到达Redis Server 以后并不是直接写入AOF文件,会将其这些命令先放入AOF缓存中进行保存。这里的AOF缓冲区实际上是内存中的一片区域,存在的目的是当这些命令达到一定量以后再写入磁盘,避免频繁的磁盘IO操作。 |
3 | AOF缓冲会根据AOF缓冲区同步文件的三种写回(fsync)策略将命令写入磁盘上的AOF文件。 |
4 | 随着写入AOF内容的增加为避免文件膨胀,会根据规则进行命令的合并(又称AOF重写),从而起到AOF文件压缩的目的。 |
5 | 当Redis Server服务器重启的时候会从AOF文件载入数据。 |
2.2 AOF配置参数
appendonly
: 是否开启AOFappendfsync
: 指定写回策略,总共三种:always
、everysec
、no
,默认为everysec
。always
: 同步写回,每个写命令执行完立刻同步地将日志写回磁盘everysec
: 每秒写回,每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区,每隔1秒把缓冲区中的内容写入磁盘no
: 操作系统控制的写回,每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
appenddirname
: AOF文件的保存路径, 不同版本的配置不同:- Redis6以及之前版本: AOF保存文件的位置和RDB保存文件的位置一样,都是读取
dir
配置 - Redis7版本: AOF保存文件的文件夹位置=
dir
+appenddirname
- Redis6以及之前版本: AOF保存文件的位置和RDB保存文件的位置一样,都是读取
appendfilename
: AOF文件名称,在Redis7中,基于新的Multi Part AOF的设计,aof文件不再是Redis7之前的单文件,有三个文件组成:base基本文件,incr增量文件,manifest清单文件。auto-aof-rewrite-percentage
: 相比上次重写文件增长占比auto-aof-rewrite-min-size
: 重写需要最小文件大小no-appendfsync-on-rewrite
: aof重写期间是否同步
2.3 开启AOF
- 修改redis.conf配置
[root@hadoop105 bin]# vi ../conf/redis.conf
将 appendonly no改为 appendonly yes
appendfsync默认配置不动
appenddirname 配置不动
appendfilename配置不动
- 重启Redis服务器
[root@hadoop105 bin]# ./redis-cli -a jack shutdown
[root@hadoop105 bin]# ./redis-server ../conf/redis.conf
[root@hadoop105 appendonlydir]# ll
总用量 8
-rw-r--r--. 1 root root 88 3月 10 20:22 appendonly.aof.1.base.rdb
-rw-r--r--. 1 root root 0 3月 10 20:22 appendonly.aof.1.incr.aof
-rw-r--r--. 1 root root 88 3月 10 20:22 appendonly.aof.manifest
2.4 AOF优缺点
- AOF优点
- 使用AOF的Redis持久化程度高:支持不同的写回策略,写回是使用后台线程执行的,基本不丢失写入日志。
- AOF日志是一个追加日志,不会出现寻道问题,也不会在断电时出现损坏问题。即使由于某种原因(磁盘已满或其他原因)日志以写一半的命令结尾,使用
redis-check-aof
工具也能够轻松修复它。 - 当 AOF 变得太大时,Redis能够在后台自动重写AOF。重写是完全安全的,因为当Redis继续附加到旧文件时,会使用创建当前数据集所需的最少操作集生成一个全新的文件,一旦第二个文件准备就绪,Redis就会切换两者并开始附加到新的那一个。
- AOF以易于理解和解析的格式依次包含所有操作的日志。您甚至可以轻松导出AOF文件。例如,即使您不小心使用
FLUSHALL
命令刷新了所有内容,只要在此期间没有执行日志重写,您仍然可以通过停止服务器、删除最新命令并重新启动Redis来保存您的数据集。
- AOF缺点
- AOF文件通常比相同数据集的RDB文件大。
- 有些写回策略下AOF可能比RDB慢。
2.5 AOF重写机制
随着Redis持久化的不断进行,AOF的文件会越来越大,文件越大占用服务器内存越大以及AOF恢复要求时间越长。为了解决这个问题,Redis新增了重写机制,当AOF文件的大小超过所设定的峰值时,Redis就会自动或者手动使用bgrewriteaof
命令启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集。
- 自动触发
## 在redis.conf默认触发条件:AOF文件大小是上次rewrite后大小的一倍且文件大于64M时进行重写
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
- 手动触发 客户端向服务器发送bgrewriteaof命令。
192.168.101.105:6379> bgrewriteaof
Background append only file rewriting started
## 查看aof文件
[root@hadoop105 appendonlydir]# ll
总用量 8
-rw-r--r--. 1 root root 88 3月 10 21:39 appendonly.aof.2.base.rdb
-rw-r--r--. 1 root root 0 3月 10 21:39 appendonly.aof.2.incr.aof
-rw-r--r--. 1 root root 88 3月 10 21:39 appendonly.aof.manifest
- 重写流程
a. Redis的父进程进行forks一个子进程。
b. 子进程开始读取Redis数据库数据生成写指令到一个新的base临时aof文件.
c. 父进程额外创建新的一个增量aof文件并往里面记录写指令,这样做即使重写失败,旧的base文件和增量文件仍然记录涵盖了所有Redis数据。
d. 当子进程重写到base临时aof文件完成,父进程就用新的增量aof文件信息和base临时aof文件信息去重建manifest文件。
e. Redis将使用base临时aof文件生成新的base文件和删除旧的增量文件。
其中b步骤将使用旧的aof文件多个记录同一个key的操作压缩成最新的一个记录,比如多个set k1 v1
,set k1 v2
变成一个set k1 v2
写记录
3. RDB+AOF混合持久化
Redis支持RDB和AOF同时开启,RDB和AOF共存时,Redis重启加载AOF的优先级更高,
3.1 开启混合方式
更改redis.conf文件配置
[root@hadoop105 appendonlydir]# vi ../conf/redis.conf
## yes表示开启,no表示禁用,默认开启😷
aof-use-rdb-preamble yes
混合持久化的最佳分配:RDB镜像做全量持久化,AOF做增量持久化。 先使用RDB进行快照存储,然后使用AOF持久化记录所有的写操作,当重写策略满足或手动触发重写的时候,将最新的数据存储为新的RDB记录。这样的话,重启服务的时候会从RDB和AOF两部分恢复数据,既保证了数据完整性,又提高了恢复数据的性能。简单来说:混合持久化方式产生的文件一部分是RDB格式,一部分是AOF格式。