博观而约取,厚积而薄发。
1. 持久化
Redis持久化的方案有两种:
2. RDB持久化
在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里。默认文件是dump.rdb,存储的是二进制数据
dump.rdb
文件数据如下:
REDIS0009� redis-ver5.0.3�
redis-bits�@�ctime��i�^used-mem��v
�
aof-preamble���nameydongynum�dage��l�ES�Y
2.1 触发RDB快照
SAVE
:当SAVE
命令执行时,会阻塞Redis服务器进程,直到RDB文件创建完毕为止,在服务器进程阻塞期间,服务器不能处理任何命令请求,也就是客户端发送的所有命令请求都会被拒绝,只有在服务器执行完SAVE
命令、重新开始接受命令请求之后,客户端发送的命令才会被执行。
127.0.0.1:6379> set name ydongy
OK
127.0.0.1:6379> save
OK
127.0.0.1:6379>
BGSAVE
:发送指令Redis会fork
一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何IO操作的,可以继续接受客户端发送过来的指令。可以通过lastsave
命令获取最后一次成功执行快照的时间。
127.0.0.1:6379> set age 22
OK
127.0.0.1:6379> BGSAVE
Background saving started
127.0.0.1:6379> LASTSAVE
(integer) 1593667361
127.0.0.1:6379>
注意:
- 执行
flushall
或者flushdb
命令,也会产生dump.rdb文件,但里面是空的,无意义 debug reload
:服务器运行过程中重启shutdown
:关闭服务器时。默认情况下执行shutdown命令时, 自动执行bgsave
(如果没有开启AOF持久化功能)
2.2 恢复快照
- 将备份文件
dump.rdb
移动到 redis 安装目录并启动服务即可,Redis服务器会自动查找该文件,前提是在配置文件中某有更改文件目录以及名称 - CONFIG GET dir获取目录
2.3 工作方式
当 Redis 需要保存 dump.rdb 文件时, 服务器执行以下操作:
- Redis 调用forks. 同时拥有父进程和子进程。
- 子进程将数据集写入到一个临时 RDB 文件中。
- 当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。
2.4 配置文件
dbfilename dump.rdb
:设置本地数据库文件名,默认值为 dump.rdb,一般设置dump-端口号.rdb
dir
:设置存储.rdb文件的路径,尽量保存在存储空间较大的目录rdbcompression yes
:设置存储至本地数据库时是否压缩数据,默认为 yes,采用 LZF 压缩rdbchecksum yes
:设置是否进行RDB文件格式校验,该校验过程在写文件和读文件过程均进行,默认为开启状态save second changes
:满足限定时间范围内key的变化数量达到指定数量即进行持久化。second:监控时间范围,changes:监控key的变化量save 900 1
:表示900s发生1次修改save 300 10
:表示300s发生10次修改save 60 10000
:表示60s发生10000次修改
优点
- RDB是一个紧凑压缩的二进制文件,存储效率较高
- RDB内部存储的是redis在某个时间间隔的数据快照,非常适合用于数据备份,全量复制等场景
- RDB恢复数据的速度要比AOF快很多
缺点
- RDB方式无论是执行指令还是利用配置,无法做到实时持久化,具有较大的可能性丢失数据
- 基于fork创建子进程,内存产生额外消耗
- 宕机带来的数据丢失风险
- 存储数据量较大,效率较低,基于快照思想,每次读写都是全部数据,当数据量巨大时,效率非常低
3. AOF
以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。默认的存储文件为:appendonly.aof
appendonly.aof
文件数据如下:
*2
$6
SELECT
$1
0
*3
$3 # 表示set占3个字符长度
set
$4 # 表示name(key)占4个字符长度
name
$6 # 表示ydongy(value)占6个字符长度
ydongy
*3
$3
set
$3 # 表示age(key)占3个字符长度
age
$2 # 表示20(value)占2个字符长度
20
3.1 AOF写数据三种策略
always(每次)
:命令写入aof_buf后立即调用系统fsync操作同步到AOF文件,fsync完成后线程返回。这种情况下,每次写入操作均同步到AOF文件中,数据零误差,硬盘IO成为性能瓶颈,性能较低everysec(每秒)
:命令写入aof_buf后调用系统write操作,write完成后线程返回;fsync同步文件操作由专门的线程每秒调用一次,将缓存区中的指令同步到AOF文件中,数据准确性较高,性能较高。在系统突然宕机的情况下丢失1秒内的数据no(系统控制)
:命令写入aof_buf后调用系统write操作,不对AOF文件做fsync同步;同步由操作系统负责,通常同步周期为30秒。这种情况下,文件同步的时间不可控,且缓冲区中堆积的数据会很多,数据安全性无法保证。
系统调用write和fsync说明:
- write操作会触发延迟写( delayed write) 机制, Linux在内核提供页缓冲区用来提高硬盘IO性能。 write操作在写入系统缓冲区后直接返回。 同步硬盘操作依赖于系统调度机制, 例如:缓冲区页空间写满或达到特定时间周期。 同步文件之前, 如果此时系统故障宕机, 缓冲区内数据将丢失
- fsync针对单个文件操作( 比如AOF文件) , 做强制硬盘同步, fsync将阻塞直到写入硬盘完成后返回, 保证了数据持久化。
3.2 AOF启动、修复、恢复
-
启动
- 修改配置文件中默认的
appendonly no
,改为yes - 配置
appendfsync always|everysec|no
三个AOF写数据策略任意选择一个, - 配置
appendfilename filename
AOF持久化文件名,默认文件名为appendonly.aof,建议配置为appendonly-端口号.aof - 配置
dir
AOF持久化文件保存路径,与RDB持久化文件保持一致即可
- 修改配置文件中默认的
-
恢复
将有数据的aof文件复制一份保存到对应目录(config get dir),重启redis然后重新加载
-
修复
服务器可能在程序正在对 AOF 文件进行写入时停机, 如果停机造成了 AOF 文件出错(corrupt), 那么 Redis 在重启时会拒绝载入这个 AOF 文件, 从而确保数据的一致性不会被破坏。当发生这种情况时, 可以用以下方法来修复出错的 AOF 文件:- 为现有的 AOF 文件创建一个备份。
- 使用 Redis 附带的 redis-check-aof 程序,对原来的 AOF 文件进行修复:
$ redis-check-aof –fix
- (可选)使用 diff -u 对比修复后的 AOF 文件和原始 AOF 文件的备份,查看两个文件之间的不同之处。
- 重启 Redis 服务器,等待服务器载入修复后的 AOF 文件,并进行数据恢复。
3.3 AOF重写
随着命令不断写入AOF,文件会越来越大,为了解决这个问题,Redis引入了AOF重写机制压缩文件体积。 AOF文件重
写是将Redis进程内的数据转化为写命令同步到新AOF文件的过程。 简单说就是将对同一个数据的若干个条命令执行结
果转化成最终结果数据对应的指令进行记录,可以使用命令bgrewriteaof
- 重写指令
127.0.0.1:6379> BGREWRITEAOF
Background append only file rewriting started
127.0.0.1:6379>
- 重写规则
- 进程内已超时的数据不再写入文件
- 忽略无效指令,重写时使用进程内数据,然后直接生成,这样新的AOF文件只保留最终数据的写入命令,如:
del key
,get key1
都会被忽略掉。 - 对同一数据的多条写命令合并为一条命令,如:
set key 1
,set key 2
,lpush list1 a
,lpush list1 2
,最终保存在aof文件中命令就只有set key 2
,lpush list1 a 2
3.4 AOF工作流程
3.5 AOF重写流程
3.6 RDB VS AOF
4 总结
RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储
AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以redis协议追加保存每次写的操作到文件末尾,Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大。
RDB与AOF的选择:
- 对数据非常敏感,建议使用默认的AOF持久化方案
- AOF持久化策略使用everysecond,每秒钟fsync一次。该策略redis仍可以保持很好的处理性能,当出
现问题时,最多丢失0-1秒内的数据。 - 注意:由于AOF文件存储体积较大,且恢复速度较慢
- 数据呈现阶段有效性,建议使用RDB持久化方案
- 数据可以良好的做到阶段内无丢失(该阶段是开发者或运维人员手工或通过脚本维护的),且恢复速度较快,阶段点数据恢复通常采用RDB方案
- 注意:利用RDB实现紧凑的数据持久化会使Redis性能降的很低
- 综合比对
- 如能承受数分钟以内的数据丢失,且追求大数据集的恢复速度,选用RDB
- 灾难恢复选用RDB
- 双保险策略,同时开启 RDB 和 AOF,重启后,Redis优先使用 AOF 来恢复数据,降低丢失数据的量