# Redis的持久化RDB、fork、copyonwrite、AOF、RDB&AOF混合使用
Redis作为数据库:
缓存时:数据是可以丢的;追求速度;
数据库:数据绝对不能丢;速度之外再加上持久性,因为内存的特点就是掉电易失
一般会把Redis+MySQL都作为数据库,Redis作为前置库,但是由于Redis写入快,而MySQL肯定写入慢于Redis,怎么保证两边的数据一致性呢?所以一般MySQL就不要开启强一致性,不要追平,采用消息队列比如Kafka等异步写入MySQL。
# Redis的单机持久化
存储层持久化的两种方案:
- 快照/副本,异地存储等
- 日志(增删改等写操作的指令)
上述两种方案,来到Redis中RDB对应快照/副本、AOF对应日志
# RDB(Redis镜像)
RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储。
RDB(Redis镜像)这种基于快照/副本,它的可靠性保障是具有时点性:
时点性:例如Redis中内存有2G数据,然后每小时拍快照落一个文件,那么比如说8点落了一个文件,这2G数据在内存到8点不可能瞬间落地到磁盘,会有个延续期,比如8点开始落地文件,8点10分结束,那么问题来了,落地文件是8点时刻的数据还是8点10分那一刻的数据呢?还是说记录着8点到8点10分状态变化的数据,这三种是哪一种呢?答案肯定是8点时刻的数据,那么是如何实现的呢?交由自己来实现怎么想问题呢?
拍快照落数据如何实现?
想个具体一点的场景:8点这个时刻,内存中有两个数据分别是
(a=3)
、(b=4)
,现在要将他们拍快照落地文件归属时点为8点,落地持续时间为10分钟。
一种做法是,阻塞程序,拍快照落地文件这个期间,不对外提供Redis服务,直到落地文件,阻塞解除,可能结束时间为8点10分,但是落地文件db.file是隶属于8点的时点数据的
这种方案的缺点就是不对外提供Redis服务导致服务不可用,在生产环境种是不能容忍的。一般企业上是不采用这种方案的。
所以另一种就是非阻塞,拍快照落地文件这个期间,还继续对外提供Redis服务,还能同时落地文件,该落地文件属于8点时点数据还是8点10分时点数据呢?那么对于时点混乱怎么解决?
时点混乱是什么?假设8点时刻,开始落地文件,将
(a=3)
写入文件,8点1分时刻修改了b的数据为(b=6)
,然后写入将(b=6)
写入文件,但是如果8点1分时刻修改了a的数据为(a=4)
,这时如何处理?每当快要结束时,前面的数据发生了更改,那么就会永远结束不了,那么一个进程中既写入数据,又做持久化落地数据,很难保证落地文件中数据是哪个时点的,这就是时点混乱。
那么如何解决时点混乱呢?就需要Linux操作系统的常识了,以下为补充知识点:
Linux系统当中的一个知识:管道;fork系统调用;copyonwrite机制(写时复制机制)
管道:
1,衔接,前一个命令的输出作为后一个命令的输入
2,管道会触发创建【子进程】
[root@redis-01 ~]# echo $$ 53775 # $$ 优先级高于 |(管道) 所以系统会先算出$$=53775 然后执行管道等 [root@redis-01 ~]# echo $$ | more 53775 [root@redis-01 ~]# echo $BASHPID 53775 # $BASHPID 优先级低于 |(管道) 所以系统会执行管道,创建子进程 然后echo $BASHPID获取子进程的id等 [root@redis-01 ~]# echo $BASHPID | more 54012 [root@redis-01 ~]# echo $BASHPID | more 54023 [root@redis-01 ~]# echo $BASHPID | more 54025 [root@redis-01 ~]# echo $BASHPID | more 54027
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16# 查看etc目录详细信息 一屏装不下,怎么分屏看 [root@redis-01 ~]# ls -l /etc # 使用管道连接more命令 达到分屏看 [root@redis-01 ~]# ls -l /etc | more # 定义num变量 赋值为0 [root@redis-01 ~]# num=0 # 打印num 0 [root@redis-01 ~]# echo $num 0 # 发生计算 num+1 [root@redis-01 ~]# ((num++)) # 再次打印num 1 [root@redis-01 ~]# echo $num 1 # 这次后接管道 发生计算 num+1 但是由于管道两边开启两个子进程,所以num+1,加的是子进程中的num [root@redis-01 ~]# ((num++)) | echo ok ok # 所以打印父进程的num 还是1 [root@redis-01 ~]# echo $num 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20通过上面演示,得出使用Linux的时候有父子进程的概念:
常规思想:进程间是要数据隔离的
# 打印父进程的id [root@redis-01 ~]# echo $$ 53775 # 打印父进程的num 1 [root@redis-01 ~]# echo $num 1 # 在启动bash是子进程 [root@redis-01 ~]# /bin/bash # 打印子进程的id [root@redis-01 ~]# echo $$ 54045 # pstree 可以看到进程的关系 确定是父子进程 [root@redis-01 ~]# pstree systemd─┬─VGAuthService ├─abrt-watch-log ├─abrtd ├─agetty ├─anacron ├─auditd───{auditd} ├─containerd───19*[{containerd}] ├─crond ├─dbus-daemon ├─dockerd───17*[{dockerd}] ├─irqbalance ├─lvmetad ├─master─┬─pickup │ ├─qmgr │ └─trivial-rewrite ├─polkitd───6*[{polkitd}] ├─4*[redis-server───3*[{redis-server}]] ├─rsyslogd───2*[{rsyslogd}] ├─sshd───sshd───bash───bash───pstree ├─systemd-journal ├─systemd-logind ├─systemd-udevd ├─tuned───4*[{tuned}] └─vmtoolsd───2*[{vmtoolsd}] # 打印子进程的num 空的 [root@redis-01 ~]# echo $num # 退出子进程 [root@redis-01 ~]# exit exit # pstree 可以看到进程的关系 可以看到退出了一层bash [root@redis-01 ~]# pstree systemd─┬─VGAuthService ├─abrt-watch-log ├─abrtd ├─agetty ├─anacron ├─auditd───{auditd} ├─containerd───19*[{containerd}] ├─crond ├─dbus-daemon ├─dockerd───17*[{dockerd}] ├─irqbalance ├─lvmetad ├─master─┬─pickup │ ├─qmgr │ └─trivial-rewrite ├─polkitd───6*[{polkitd}] ├─4*[redis-server───3*[{redis-server}]] ├─rsyslogd───2*[{rsyslogd}] ├─sshd───sshd───bash───pstree ├─systemd-journal ├─systemd-logind ├─systemd-udevd ├─tuned───4*[{tuned}] └─vmtoolsd───2*[{vmtoolsd}]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69进阶思想:父进程可以让子进程看到数据num
# 打印父进程的num 1 [root@redis-01 ~]# echo $num 1 # 导出变量num [root@redis-01 ~]# export num # 启动子进程bash [root@redis-01 ~]# /bin/bash # 打印子进程的num 1 就取到1了 [root@redis-01 ~]# echo $num 1 # 退到父进程 [root@redis-01 ~]# exit exit
1
2
3
4
5
6
7
8
9
10
11
12
13那么带来的问题是:
export的环境变量,子进程的修改不会破坏父进程
# 现在是父进程下打印num, 父进程与子进程都有num变量 [root@redis-01 ~]# echo $num 1 # 做个脚本,做个实验 [root@redis-01 ~]# vim test.sh #!/bin/bash # 需要启动bash去执行,所以肯定是子进程去执行 echo $$ # 打印子进程的id echo $num # 打印子进程num 当初是由父进程export num 给子进程的 num=999 # 修改子进程num=999 验证是否有权限修改 echo num:$num # 再次打印子进程num 是否变为999 sleep 20 # 休眠20秒 echo $num # 最后打印子进程num 验证是否修改 # test.sh 添加可执行权限 [root@redis-01 ~]# chmod +x test.sh # 后台运行test.sh 后台运行命令后加上& [root@redis-01 ~]# ./test.sh & [1] 54228 [root@redis-01 ~]# 54228 # 打印子进程id 1 num:999 # 修改子进程num=999 [root@redis-01 ~]# echo $$ # 按回车键回到父进程,打印父进程id 53775 [root@redis-01 ~]# echo $num # 打印父进程num 1 1 [root@redis-01 ~]# 999 # 休眠20秒后 打印子进程num [1]+ Done ./test.sh # 以上验证了 父进程export变量这种 子进程的修改不会影响到父进程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32父进程的修改也不会破坏子进程
# 打印父进程id [root@redis-01 ~]# echo $$ 53775 # 打印父进程num [root@redis-01 ~]# echo $num 1 [root@redis-01 ~]# ./test.sh & [1] 54254 [root@redis-01 ~]# 54254 # 打印子进程id 1 num:999 # 修改子进程num=999 [root@redis-01 ~]# echo $num # 打印父进程num 1 1 [root@redis-01 ~]# num=888 # 修改父进程num=888 [root@redis-01 ~]# echo $num # 打印父进程num 888 888 [root@redis-01 ~]# 999 # 休眠20秒后 打印子进程num [1]+ Done ./test.sh # 以上验证了 父进程export变量这种 父进程的修改不会影响到子进程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21创建子进程的速度应该是什么程度?如果父进程是redis,内存数据比如10G,若想做到非阻塞的,还要落到为一个时点数据文件的,那么就是8点这个时点来到后,Redis的父进程创建出子进程,相当于父进程的副本,然后父进程接收客户端的响应,提供对外服务,而子进程就去落地时点数据。整体逻辑是这样,但是带来的问题:
1、创建子进程(副本)速度问题;
2、副本空间问题,之前就已经是10G,再加上副本,空间是否够用;
针对上述问题:可以使用fork系统调用实现:其实玩的就是指针。达到速度快,并且空间要求不是很多。
fork系统调用原理解析:
1、首先常识:物理内存地址是通过程序的虚拟内存地址映射寻址过来的。
2、假设Redis的进程中虚拟地址空间中有个a变量,它的虚拟地址是3,我们用
父虚拟(a,3)
表示,父虚拟(a,3)
映射到物理(8,hello)
,那么Redis取a时就将hello取出来;3、Redis创建子进程(fork),子进程也有自己的虚拟地址空间有个a变量,它的虚拟地址是3,我们用
子虚拟(a,3)
表示,子虚拟(a,3)
也映射到物理(8,hello)
;4、所以fork过程,只是多了指针引用(映射),并不会多一份数据的;
5、当父进程修改a,或者子进程修改a时会触发copy on write(写时复制),创建子进程并不发生复制,这样创建子进程变快了,根据经验,不可能父子进程把所有数据都改一遍,触发写时复制的机会也不多,比如:父进程要将a修改为world,那么先将物理内存中出现
物理(9,world)
,再由父虚拟(a,3)
映射到物理(9,world)
,完成写时复制。其实成本不高,玩的是指针。子进程修改也一样。补充完后,回到拍快照落数据如何实现?
Redis的RDB(快照)落数据如何实现?非阻塞实现(续)
8点开始落地文件,Redis进程fork出子进程,父进程继续向客户端提供服务,当父进程中数据发生修改,触发copy on write写时复制,在物理内存新增数据,然后父进程的数据指向新的物理内存地址,子进程读取数据写入落地文件,该文件属于8点时点数据。
RDB的实现方式:
人工实现,命令执行
save
前端阻塞,落地文件,使用场景明确,就是关机维护或者停止服务的前提下使用
bgsave
后台非阻塞,落地文件,使用场景一般较多,就是不能停服务的前提下使用
配置文件编写bgsave规则,自动化实现落地文件
注意:配置文件中使用save这个标识来代表bgsave的指令
例如:
save <seconds> <changes> # seconds:给定的秒数 changes:对数据库执行的写入操作数 # 900秒(15分钟)后,如果至少有1个key更换,则触发bgsave save 900 1 # 300秒(5分钟)后,如果至少更改了10个key,则触发bgsave save 300 10 # 60秒后,如果至少10000个key发生更改,则触发bgsave save 60 10000 # 文件名称 dbfilename dump.rdb # 文件所在目录 dir /var/lib/redis/6379
1
2
3
4
5
6
7
8
9
10
11
12
13RDB的弊端:
不支持拉链,只有一个dump.rdb
丢失数据相对多一些,时点与时点之间窗口数据容易丢失
例如:8点得到一个rdb,9点刚要落一个rdb,挂机了,那么就丢失一个小时的数据了
RDB的优点:
类似java中的序列化,恢复的速度相对快
# AOF(Append Only File)
AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以redis协议追加保存每次写的操作到文件末尾.Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大。
Redis中,RDB和AOF可以同时开启,同时开启两种持久化方式, 在这种情况下, 当Redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整,4.0版本以后AOF文件中包含RDB全量,增加记录新的写操作在后面,那么在数据恢复的时候先执行RDB的那些二进制数据,再执行少量的AOF指令集,这样充分利用两种方案的优点,达到速度快的效果。
那么这种方式落文件会有个显著的问题:例如:
Redis运行了10年,开启了AOF,在10年头上,Redis挂掉了,那么:
- AOF文件多大?很大,比如说10T,因为是Append Only File,不会修改文件的只往里面添加数据。
- 数据恢复会不会溢出?不会溢出,因为只要是线性执行文件,就像当初执行命令一样,不会溢出的。
- 数据恢复要多久?可能8、9年才能恢复完成。
AOF的弊端:
- 体量无限变大
- 恢复大
优点:丢失数据少
像这种AOF、日志类的,如果优点能保住,还是可以用的;那么就是结果:设计一个方案让日志,AOF足够小
例如:hdfs,fsimage+edits.log ,让日志只记录一个小时的增量,一个小时过后将前一个小时的日志合并到fsimage,edits.log清空,edits.log记录这个小时的增量。
Redis的设计方案是:
4.0以前
重写:删除抵消的命令,合并重复的命令,最终也是一个纯指令的日志文件
4.0以后
重写:将老的数据RDB写入到aof文件中,将增量的以指令的方式追加到AOF文件,AOF是一个混合体
利用了RDB的快,利用了日志的全量数据优势
AOF由于是写操作都要记录到文件中,会触发IO,但是Redis是内存数据库,这样势必会拖慢Redis。
补充常识:所有程序调用磁盘和硬件的操作及IO,需要内核程序(kernel);
比如:Redis进程触发写操作,该进程调用内核程序(kernel)建立文件描述符fd8,内核给文件描述符fd8开辟一个buffer缓冲区,那么Redis进程先往buffer缓冲区写入数据,当buffer缓冲区满了之后,内核会将buffer缓冲区的数据向磁盘刷写。
针对这个问题,AOF有三个级别:
# 发生一次写操作,就向磁盘刷写。这种数据最可靠,最多丢失一条数据 appendfsync always # 每秒向磁盘刷写。可能最大丢失无限接近buffer缓冲区大小的数据,但是总是比buffer缓冲区大小要小的 appendfsync everysec # 相当于Redis不调用刷写操作,当buffer缓冲区满了之后,内核会将buffer缓冲区的数据向磁盘刷写。 # 说白了就是交由内核,那么可能会丢失一个buffer缓冲区大小的数据 appendfsync no # 折中选择 appendfsync everysec # AOF重写自动化设置 # Redis有记忆功能,会记住重写后AOF文件的大小,当AOF文件再次达到100%的时候,例如128mb时,触发重写 auto-aof-rewrite-percentage 100 # AOF文件达到64mb了,那么触发重写 auto-aof-rewrite-min-size 64mb
1
2
3
4
5
6
7
8
9
10
11
12
13
14演示AOF老版本不开启混合模式
### 窗口a ### # 查看redis的进程,保证没有Redis的进程 [root@redis-01 /etc/redis]# ps -ef|grep redis root 1907 1823 0 23:54 pts/0 00:00:00 grep --color=auto redis # 修改配置文件 [root@redis-01 /etc/redis]# vim 6379.conf daemonize yes 变为no 变为前端阻塞运行 #logfile /var/log/redis_6379.log 将日志文件注释掉,这样才能打印信息到控制台 appendonly no 变为yes 开启AOF # 当重写时,父进程fork子进程,子进程去写入AOF文件,这时父进程不写入AOF文件了 no-appendfsync-on-rewrite no # 关闭混合模式(RDB与AOF相结合) aof-use-rdb-preamble yes 变为no # b中执行完清除之前的持久化文件 # 启动Redis服务 [root@redis-01 /etc/redis]# redis-server /etc/redis/6379.conf ### 窗口b ### # 清除之前的持久化文件 [root@redis-01 ~]# cd /var/lib/redis/6379 [root@redis-01 /var/lib/redis/6379]# ll total 4 -rw-r--r--. 1 root root 113 Aug 25 23:54 dump.rdb [root@redis-01 /var/lib/redis/6379]# rm -rf dump.rdb [root@redis-01 /var/lib/redis/6379]# ll total 0 -rw-r--r--. 1 root root 0 Aug 26 00:07 appendonly.aof # 只有AOF文件 [root@redis-01 /var/lib/redis/6379]# vim appendonly.aof # 内容为空 # 执行完c再次查看AOF文件 [root@redis-01 /var/lib/redis/6379]# vim appendonly.aof *2 # *2 代表后面是由2个元素($6、$1)组成,$6是说后面跟的这个长度为6,$1也是这样 $6 # 这样能够正确切割字符获取指令了 SELECT $1 0 *3 $3 set $2 k1 $5 hello [root@redis-01 /var/lib/redis/6379]# vim appendonly.aof *2 $6 SELECT $1 0 *3 $3 set $2 k1 $5 hello *3 $3 set $2 k2 $4 ooxx [root@redis-01 /var/lib/redis/6379]# ll total 8 -rw-r--r--. 1 root root 86 Aug 26 00:17 appendonly.aof -rw-r--r--. 1 root root 116 Aug 26 00:18 dump.rdb # 生成dump.rdb文件 [root@redis-01 /var/lib/redis/6379]# vim dump.rdb REDIS0009ú redis-ver^E5.0.5ú # 二进制序列化文件开头是REDIS redis-bitsÀ@ú^EctimeÂgm&aú^Hused-memÂ^@^F^M^@ú^Laof-preambleÀ^@þ^@û^B^@^@^Bk2^Dooxx^@^Bk1^Ehelloÿ¼2HÛ¬^RFp [root@redis-01 /var/lib/redis/6379]# redis-check-rdb dump.rdb # 校验dump.rdb文件 [offset 0] Checking RDB file dump.rdb [offset 26] AUX FIELD redis-ver = '5.0.5' [offset 40] AUX FIELD redis-bits = '64' [offset 52] AUX FIELD ctime = '1629908327' [offset 67] AUX FIELD used-mem = '853504' [offset 83] AUX FIELD aof-preamble = '0' [offset 85] Selecting DB ID 0 [offset 116] Checksum OK [offset 116] \o/ RDB looks OK! \o/ [info] 2 keys read [info] 0 expires [info] 0 already expired # 演示重写 [root@redis-01 /var/lib/redis/6379]# vim appendonly.aof *2 $6 SELECT $1 0 *3 $3 set $2 k1 $5 hello *3 $3 set $2 k2 $4 ooxx *3 $3 set $2 k1 $1 a *3 $3 set $2 k1 $1 b *3 $3 set $2 k1 $1 c ## 记录着很多重复指令,过时的指令,如何让AOF文件变小 [root@redis-01 /var/lib/redis/6379]# ll total 8 -rw-r--r--. 1 root root 170 Aug 26 00:24 appendonly.aof # 现在大小是170 -rw-r--r--. 1 root root 116 Aug 26 00:18 dump.rdb # c中执行完BGREWRITEAOF AOF文件变小了 [root@redis-01 /var/lib/redis/6379]# ll total 8 -rw-r--r--. 1 root root 82 Aug 26 00:28 appendonly.aof # 大小是82 -rw-r--r--. 1 root root 116 Aug 26 00:18 dump.rdb [root@redis-01 /var/lib/redis/6379]# vim appendonly.aof *2 $6 SELECT $1 0 *3 $3 SET $2 k2 $4 ooxx *3 $3 SET $2 k1 $1 c ### 窗口c ### [root@redis-01 ~]# redis-cli # 连接redis 127.0.0.1:6379> set k1 hello # 执行set指令 OK 127.0.0.1:6379> set k2 ooxx OK 127.0.0.1:6379> bgsave # 执行bgsave 生成dump.rdb文件 Background saving started # 演示重写 127.0.0.1:6379> keys * 1) "k2" 2) "k1" 127.0.0.1:6379> set k1 a OK 127.0.0.1:6379> set k1 b OK 127.0.0.1:6379> set k1 c # 执行同一key的修改 OK 127.0.0.1:6379> get k1 "c" 127.0.0.1:6379> BGREWRITEAOF # 让AOF文件变小 执行BGREWRITEAOF 后台重写AOF Background append only file rewriting started
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184演示AOF新版本开启混合模式
### 窗口b ### # 清除之前的持久化文件 [root@redis-01 ~]# cd /var/lib/redis/6379 [root@redis-01 /var/lib/redis/6379]# ll total 8 -rw-r--r--. 1 root root 82 Aug 26 00:28 appendonly.aof -rw-r--r--. 1 root root 112 Aug 26 00:32 dump.rdb [root@redis-01 /var/lib/redis/6379]# rm -rf ./* [root@redis-01 /var/lib/redis/6379]# ll total 0 # a中启动Redis服务后 [root@redis-01 /var/lib/redis/6379]# ll total 0 -rw-r--r--. 1 root root 0 Aug 26 00:36 appendonly.aof # 会多一个AOF文件,内容是空的 # c中执行set的指令 [root@redis-01 /var/lib/redis/6379]# vim appendonly.aof *2 $6 SELECT $1 0 *3 $3 SET $2 k1 $1 a *3 $3 SET $2 k1 $1 b *3 $3 SET $2 k1 $1 c *3 $3 SET $2 k1 $1 d # c中执行BGREWRITEAOF [root@redis-01 /var/lib/redis/6379]# vim appendonly.aof # 内容变为RDB的内容 REDIS0009ú redis-ver^E5.0.5ú redis-bitsÀ@ú^EctimeÂ`r&aú^Hused-mem¸^E^M^@ú^Laof-preambleÀ^Aþ^@û^A^@^@^Bk1^Adÿ^L¨r²êý@t # c中再次执行set k1 # 再次查看AOF 后边添加AOF内容 [root@redis-01 /var/lib/redis/6379]# vim appendonly.aof REDIS0009ú redis-ver^E5.0.5ú redis-bitsÀ@ú^EctimeÂ`r&aú^Hused-mem¸^E^M^@ú^Laof-preambleÀ^Aþ^@û^A^@^@^Bk1^Adÿ^L¨r²êý@t*2^M # 前面是二进制的RDB,加快运算速度 # 后面是RDB时点之后的增量指令 # 这就是增量日志+全量时点数据,这种恢复速度快,因为日志不是全量的了 $6^M SELECT^M $1^M 0^M *3^M $3^M set^M $2^M k1^M $1^M w^M *3^M $3^M set^M $2^M k1^M $1^M m^M ### 窗口a ### # 修改配置文件 [root@redis-01 /etc/redis]# vim 6379.conf # 开启混合模式(RDB与AOF相结合) aof-use-rdb-preamble no 变为yes # 启动Redis服务 [root@redis-01 /etc/redis]# redis-server /etc/redis/6379.conf ### 窗口c ### [root@redis-01 ~]# redis-cli # 连接redis 127.0.0.1:6379> set k1 a OK 127.0.0.1:6379> set k1 b OK 127.0.0.1:6379> set k1 c OK 127.0.0.1:6379> set k1 d OK 127.0.0.1:6379> BGREWRITEAOF # 触发重写,AOF文件变为混合模式 Background append only file rewriting started # 再次set k1 127.0.0.1:6379> set k1 w OK 127.0.0.1:6379> set k1 m OK
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111