今天我们来讲Redis的持久化。
一、为什么Redis要持久化?
我们都知道,Redis运行时是将数据保存在内存中的,如果服务器宕机或者重启,内存中的数据必然会丢失。所以,必须要把数据持久化到磁盘,以便服务器故障时进行数据恢复。
二、Redis持久化的两种方式
Redis持久化提供了两种方式,RDB(RedisDB)和AOF(appendonly File)。
1. RDB
RDB即RedisDB的缩写,即将整个Redis内存数据持久化到一个文件。
有小伙伴可能会问,Redis在做持久化的同时,内存数据被修改了怎么办。
如上图,Redis持久化操作前a的值是1,持久化过程当中a变为2。
请问在持久化结束时,持久化文件中a的值记的是多少?
这里,必须要提到一个知识点:linux的子进程创建函数:fork。
[root@localhost ~]# man fork
fork() creates a new process by duplicating the calling process. The new process is referred to as the child process. The calling process is referred to as the parent process.
The child process and the parent process run in separate memory spaces. At the time of fork() both memory spaces have the same content. Memory writes, file mappings (mmap(2)), and unmappings (munmap(2)) performed by one of the processes do not affect the other.
通过查看linux手册发现,fork函数会通过复制主进程的方式快速创建一个新的进程:子进程。在fork调用发生时,子进程和主进程有相同的数据内容,主子进程运行在各自的内存空间,互不影响。
Redis就是通过调用fork方式创建子进程进行数据的持久化,所以会保留了持久化开始时刻的数据状况。
所以,上面那个问题,a的值还是1。
当子进程在进行数据持久化时,redis主进程会继续对外提供服务,不受影响。
关于RDB,Redis提供了2种方式:命令和配置文件。
可以通过 save (阻塞)和 bgsave 命令,触发持久化写文件操作。
127.0.0.1:6379> bgsave
Background saving started
127.0.0.1:6379>
另外一种方式就是配置文件,Redis默认开启。
save 900 1 //900s有一个key被修改时保存
save 300 10 //300s内有10个key被修改时保存
save 60 10000 //60s内有10000个key被修改时保存
执行持久化之后,会在指定的目录下生成一个 dump.rdb 二进制文件。
[root@localhost ~]# cd /var/lib/redis/6379
[root@localhost 6379]# ll
总用量 8
-rw-r--r--. 1 root root 176 12月 28 20:34 dump.rdb
RDB生成目录以及文件名配置:
# The filename where to dump the DB
dbfilename dump.rdb
# Note that you must specify a directory here, not a file name.
dir /var/lib/redis/6379
[root@localhost 6379]# vi dump.rdb
REDIS0009ú redis-ver^E6.0.9ú
redis-bitsÀ@ú^EctimeÂÅÞé_ú^Hused-memÂØ<93>^L^@ú^Laof-preambleÀ^@þ^@û^B^@^@À^AÀ^A^@^AaÀ^Cÿ<9d>Uî;hÕà<9d>
所以,一句话总结,RDB就是在特定的条件下,将Redis的内存数据快照以二进制的方式保存到磁盘。
RBD的优点是,全量数据二进制文件,数据恢复快。
缺点是,可能会丢数据。
2. AOF
顾名思义,AOF会将redis中每一步对数据修改的操作记录(日志)append到相应的文件中。
在redis中配置如下:
appendonly yes
# The name of the append only file (default: "appendonly.aof")
appendfilename "appendonly.aof"
为了降低IO消耗,AOF写文件时,会先将数据写到缓冲区,然后再把缓冲区的内容 flush 到磁盘,这个过程叫做 fsync。
AOF的flush频率有三种:
appendfsync always //每次写操作都flush,影响性能
appendfsync everysec //每秒flush
appendfsync no //消极等待OS刷新(一般30s),可能丢失数据
相比于always的激进和no的消极,everysec在性能和数据完整性上取了一个折中。
bgrewirteaof
随着服务器运行时间越来越长,AOF文件也势必会越来越大,bgrewirteaof(AOF重写)就是为了解决这个问题。
拆开来看 bgrewirteaof = bg(background)+rewrite+aof, 即 bgrewirteaof 会在后台起子进程,对aof文件进行rewrite操作。重写时,aof文件中的命令会被整理(命令相互抵消、整合等),重写后的aof会变小。
来,我们实践一下。
[root@localhost 6379]# redis-cli
127.0.0.1:6379> set a 1
OK
127.0.0.1:6379> set a 2
OK
127.0.0.1:6379> set a 3
OK
[root@localhost 6379]# ll
总用量 8
-rw-r--r--. 1 root root 258 12月 28 21:19 appendonly.aof
[root@localhost 6379]# vi appendonly.aof
SELECT
$1
0
*3
$3
set
$1
a
$1
1
*3
$3
set
$1
a
$1
2
*3
$3
set
$1
a
$1
3
127.0.0.1:6379> BGREWRITEAOF
Background append only file rewriting started
[root@localhost 6379]# ll
总用量 8
-rw-r--r--. 1 root root 77 12月 28 21:25 appendonly.aof
[root@localhost 6379]# vi appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
SET
$1
a
$1
3
~
可以看到,在对变量a进行三次赋值操作后,appendonly.aof记录下了每次执行的命令,文件大小是 258 字节。执行 bgrewirteof 之后,文件大小变为77字节,命令被合并成一条,即 set a 3。
但是,这里又会有新的问题,bgrewirteof 对历史命令的合并是非常耗费性能的,尤其是数据量非常大的情况下。
此时,便产生了持久化的混合模式。在redis 4.0之后,开始支持。即执行bgrewirteof之后,将当前数据全量以RDB的方式写入appendonly文件的前半部分,之后的命令再以 append 的方式进行追加。
REDIS0009ú redis-ver^E6.0.9ú
redis-bitsÀ@ú^EctimeÂ<90>âé_ú^Hused-memÂø3^M^@ú^Laof-preambleÀ^Aþ^@û^B^@^@^AaÀ^C^@À^AÀ^AÿFlÜ»CÖ:¦*2^M
$6^M
SELECT^M
$1^M
0^M
*3^M
$3^M
set^M
$1^M
a^M
$1^M
1^M
~
混合模式开关设置:
aof-use-rdb-preamble yes
混合模式兼顾了RDB数据恢复快以及AOF数据完整性的优点。
bgrewirteof的触发机制是怎样的呢?
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
即Redis会在 appendonly.aof 到达64M(rewrite最小大小),128M(64M+64*100%),192M…时,自动执行bgrewriteof。
所以,一句话总结: AOF会详细记录Redis的每一步写操作。由于AOF文件的数据可靠性,Redis恢复数据时,会使用AOF(若有)。
Redis原话:
AOF and RDB persistence can be enabled at the same > time without problems.
If the AOF is enabled on startup Redis will load t> he AOF, that is the file
with the better durability guarantees.
三、总结
稍微总结一下,今天我们分享了redis的两种持久化方式,RDB和AOF。
RDB的优点是:
- 二进制压缩文件,恢复速度快
RDB缺点是:
- 可能丢失数据
AOF的优点是:
- 不易丢失数据,数据完整性好
AOF的缺点是:
- 每一步操作都记录,相对影响性能
- 数据恢复慢,文件较大
具体使用场景上,数据重要性不高,且要求性能,可以使用Redis默认的RDB方式。如果数据完整性要求较高,则可以使用AOF和RDB结合的方式。
最后,简单整理了个脑图,方便记忆。
好了,今天分享就是这样,如果觉得有用,欢迎三连(点赞、在看、转发)。