个人博客地址:
Redis 持久化机制
1. 概述
Redis
为了保证性能,会将所有数据放在内存中,那么万一Redis宕机,数据岂不是全部丢失了?
不要怕,Redis自然想到了这一点,它提供了三种持久化机制将内存中的数据持久化到磁盘中。
-
RDB
快照方式持久化(snapshot),快照在Linux就已经学过,保存所有数据的状态,下次开机直接按照这个状态恢复。
因为保存的快照是以.rdb结尾的文件,故称此方式为RDB持久化方式。
-
AOF
(append only file)只追加日志文件,记录Redis所有写命令,下次开机将这些命令全部执行,即可恢复数据。
-
混合型持久化
RDB虽然快,但是数据丢失问题较为严重;AOF虽然能保证数据安全,但是执行所有命令需要很长时间。
所以Redis4.x以后,将两种方式结合,RDB文件的内容放在AOF文件中,以.aof文件的形式存储。在恢复数据时,先加载rdb的内容,再执行aof的内容。缺点是两种格式混合在一起难以阅读。
需要注意的是,不论是哪种方式,都无法保证数据的绝对安全。
2. RDB
snapshot想必大家已经不陌生了,Linux已经接触过这个机制:保存现在的状态,随时准备恢复。
拍摄的快照以**.rdb**的形式保存在磁盘中。
假如在Redis宕机之前拍摄的快照为:
那么下次开机就可以即将这两个数据恢复。
Redis提供了两种拍摄快照的方式 :自动、手动。其中手动拍摄快照有两个命令:save、bgsave
2.1 手动快照
-
save
由主进程完成快照的拍摄,持久化过程中其他命令阻塞。
-
bgsave
background save,主线程fork出一个子进程,由这个子进程完成持久化。
fork :
当一个进程创建子进程时,底层的操作系统会创建该进程的副本,在类unix系统中创建子进程的操作会进行优化:在刚开始的时候,父子进程共享相同内存,直到父进程/子进程对内存进行写操作后结束共享,各用各的。
2.2 自动快照
在redis.conf配置文件中存在,参数如下:(版本不同,默认参数不同)
# * After 3600 seconds (an hour) if at least 1 key changed
# * After 300 seconds (5 minutes) if at least 100 keys changed
# * After 60 seconds if at least 10000 keys changed
# save 3600 1
# save 300 100
# save 60 10000
解释 :
1h内有一个键被改变会触发快照拍摄。
5mins内有100个键被改变会触发快照拍摄。
1min内有10000个键被改变会触发快照拍摄。
这些快照的拍摄方式都是bgsave。
优点 :
-
rdb文件的加载速度特别快,远超aof。
-
使用单独子进程来进行持久化,主进程不会进行任何 IO 操作。
缺点 :
-
容易造成数据丢失。
-
每次拍快照都要创建子进程,浪费资源.。
3. AOF
这种机制可以将所有客户端执行的写命令记录到日志文件中,AOF
持久化会将被执行的写命令写到AOF文件末尾,以此来记录数据发生变化的全过程,因此只要Redis从头到尾执行一遍AOF文件中的命令,就可以恢复之前的数据。
3.1 AOF机制
RDB
是间隔一段时间进行持久化,如果持久化之间的时间内发生故障,会出现数据丢失。而AOF
持久化方式能很好的解决RDB
持久化方式造成的数据丢失,AOF
持久化到硬盘中的并不是内存中的数据快照,而是将所有写命令记录到日志中。
AOF能做到最多丢失1s内的数据,甚至不丢失数据。
Redis提供了三种AOF策略 :
-
appendfsync always
每执行一次写命令,都对aof文件续写。
-
appendfsync everysec
每一秒进行一次aof文件续写,这一秒的写命令都会记录。
-
appendfsync no
并不是不开启,而是将aof续写的时机交给操作系统管理,操作系统开心了就续写,不开心就不续写。
优点 :
- 保证数据丢失风险降到最低
缺点 :
- aof文件的体积会很大,同时加载速度很慢
3.2 AOF文件的重写
随着Redis
在线上运行的时间越来越久,客户端执行的命令越来越多,AOF
的文件也会越来越大。
当我们执行100次set name 张三
,其中99次都是多余的,因为想要恢复只要执行一次set name 张三
就行了。为了压缩AOF文件的体积,Redis提供了AOF文件重写机制
。
有两种方式触发AOF的重写机制:
-
手动:执行
bgrewrite
,background rewrite,不会阻塞Redis -
自动:在配置文件中进行配置
auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb
当AOF文件体积大于64MB,或者比上一次重写之后体积大了100%,会自动触发。
如果重写过于频繁,可以考虑将auto-aof-rewrite-percentage设置为更大。
重写的原理 :
重写AOF文件的操作并不是基于原本的AOF文件,而是讲真个内存中的数据库内容用命令的方式重写了一个新的AOF文件,替换原有的AOF文件,这样可以避免一些无用的命令。
4. 混合型持久化
因为RDB
虽然加载快但是存在数据丢失,AOF
数据安全但是加载缓慢,Redis
为了解决这个问题,带来了一个新的持久化选项——混合持久化。将RDB
文件的内容和增量的AOF
日志文件存在一起。这里的AOF
日志不再是全量 的日志,而是自持久化开始到持久化结束的这段时间发生的增量AOF
日志,通常这部分AOF
日志很小。Redis
重启的时候,可以先加载RDB
的内容,然后再重放增量AOF
日志,就可以完全替代之前的AOF
全量文件重放,恢复效率因此大幅得到提升(混合型持久化最终生成的文件后缀是.aof
,可以通过redis.conf
文件中aof-use-rdb-preamble yes
配置开启)。
-
优点:
结合了
RDB
和AOF
的优点,使得数据恢复的效率大幅提升 -
缺点:
兼容性不好,
Redis-4.x
新增,虽然最终的文件也是.aof
格式的文件,但在4.0
之前版本都不识别该aof
文件,同时由于前部分是RDB
格式,阅读性较差。