最新Redis高可用之持久化_redis-rdb-bgsave,2024年最新软件测试面试题选择题

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化的资料的朋友,可以戳这里获取

:
6379

info memory

向Redis中写入500万条数据后,Redis占用1.26G内存容量

Memory

used_memory
:
1347976664
used_memory_human
:
1.26G
used_memory_rss
:
1381294080
used_memory_rss_human
:
1.29G
used_memory_peak
:
1347976664
used_memory_peak_human
:
1.26G
total_system_memory
:
2080903168
total_system_memory_human
:
1.94G
used_memory_lua
:
37888
used_memory_lua_human
:
37.00K
maxmemory
:
0
maxmemory_human
:
0B
maxmemory_policy
:
noeviction
mem_fragmentation_ratio
:
1.02
mem_allocator
:
jemalloc

3.6
.
0
127.0
.
0.1
:
6379

dbsize

查看Redis中数据总数

(
integer
)

4999999


8.在系统命令提示符中查看生成的RDB文件



[root@mysql redis]# ls -lah # Redis的RDB文件经过压缩后的大小为122MB
total 122M
drwxr-x— 2 redis redis 22 Oct 13 15:31 .
drwxr-xr-x. 64 root root 4.0K Oct 13 13:38 …
-rw-r–r-- 1 redis redis 122M Oct 13 15:31 dump.rdb


**3.1.2 使用BGSAVE命令异步创建RDB文件**


执行BGSAVE命令也会创建一个新的RDB文件


BGSAVE不会造成redis服务器阻塞:在执行BGSAVE命令的过程中,Redis服务端仍然可以正常的处理其他的命令请求


**BGSAVE命令执行步骤:**


* 1.Redis服务端接受到**BGSAVE**命令
* 2.Redis服务端通过**fork()来生成一个名叫redis-rdb-bgsave的进程**,由redis-rdb-bgsave子进程来创建RDB文件,而Redis主进程则继续处理客户端的命令请求
* 3.当redis-rdb-bgsave子进程创建完成RDB文件,会**向Redis主进程发送一个信号,告知Redis主进程RDB文件已经创建完毕**,然后redis-rdb-bgsave子进程退出
* 4.Redis**服务器(父进程)接手子进程创建的RDB文件**,BGSAVE命令执行完毕


**BGSAVE命令执行过程如下图所示**  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201120143212437.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwOTA3OTc3,size_16,color_FFFFFF,t_70#pic_center)  
 Redis主进程因为**创建子进程,会消耗额外的内存**


**需要注意的是:如果在Redis主进程fork子进程的过程中花费的时间过多,Redis仍然可能会阻塞**


BGSAVE是一个异步命令,Redis客户端向Redis服务端发送BGSAVE命令后会立即得到回复,而实际的操作在Redis服务端回复之后才开始


**例子:**


现在Redis中已经有500万条数据


**1.删除Redis的RDB文件**



[root@mysql redis]# rm -rf *.rdb # 删除Redis的旧的RDB文件
[root@mysql redis]# ll
total 0


2.在redis-cli中执行BGSAVE命令



127.0.0.1:6379> bgsave # 执行BGSAVE命令后会立即得到响应
Background saving started


3.在另一个redis-cli中执行命令



127.0.0.1:6379> spop key2 # 从Redis的集合中弹出’key2’的值
“value2”
127.0.0.1:6379> dbsize # 查看Redis中所有数据的总数
(integer) 4999998
127.0.0.1:6379> info memory # 查看Redis占用的内存数

Memory

used_memory:1347973736
used_memory_human:1.26G # Redis占用了1.2G内存
used_memory_rss:1383464960
used_memory_rss_human:1.29G
used_memory_peak:1348224368
used_memory_peak_human:1.26G
total_system_memory:2080903168
total_system_memory_human:1.94G
used_memory_lua:37888
used_memory_lua_human:37.00K
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
mem_fragmentation_ratio:1.03
mem_allocator:jemalloc-3.6.0


4.在系统命令提示符中执行命令



[root@mysql redis]# ps aux | grep redis | grep -v ‘redis-cli’
redis 856 3.1 66.3 1486404 1348920 ? Ssl 13:38 3:39 /usr/bin/redis-server 0.0.0.0:6379 # Redis的主进程
root 3015 0.0 0.0 112664 968 pts/3 R+ 15:36 0:00 grep --color=auto redis
[root@mysql redis]# ps aux | grep redis | grep -v ‘redis-cli’
redis 856 3.0 66.3 1486404 1348956 ? Ssl 13:38 3:39 /usr/bin/redis-server 0.0.0.0:6379 # Redis的主进程
redis 3026 87.1 66.3 1486408 1348032 ? R 15:36 0:05 redis-rdb-bgsave 0.0.0.0:6379 # Redis主进程fork的子进程
root 3028 0.0 0.0 112664 968 pts/3 R+ 15:37 0:00 grep --color=auto redis
[root@mysql redis]# pwd
/var/lib/redis
[root@mysql redis]# ls -lah # 查看BGSAVE命令运行后得到的RDB文件
total 122M
drwxr-x— 2 redis redis 22 Oct 13 15:37 .
drwxr-xr-x. 64 root root 4.0K Oct 13 13:38 …
-rw-r–r-- 1 redis redis 122M Oct 13 15:37 dump.rdb


**SAVE命令与BGSAVE命令的区别**  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201120143654937.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwOTA3OTc3,size_16,color_FFFFFF,t_70#pic_center)  
 **RDB持久化方式的总结**



> 
> SAVE创建RDB文件的速度会比BGSAVE快,SAVE可以集中资源来创建RDB文件  
>  如果数据库正在上线当中,就要使用BGSAVE  
>  如果数据库需要维护,可以使用SAVE命令
> 
> 
> 


3.1.3 自动创建RDB文件


打开Redis的配置文件/etc/redis.conf



save 900 1
save 300 10
save 60 10000


自动持久化配置解释:



save 900 1表示:如果距离上一次创建RDB文件已经过去的900秒时间内,Redis中的数据发生了1次改动,则自动执行BGSAVE命令
save 300 10表示:如果距离上一次创建RDB文件已经过去的300秒时间内,Redis中的数据发生了10次改动,则自动执行BGSAVE命令
save 60 10000表示:如果距离上一次创建RDB文件已经过去了60秒时间内,Redis中的数据发生了10000次改动,则自动执行BGSAVE命令


当**三个条件中的任意一个条件被满足时,Redis就会自动执行BGSAVE命令**


需要注意的是:**每次执行BGSAVE命令创建RDB文件之后,服务器为实现自动持久化而设置的时间计数器和次数计数器就会被清零**,并重新开始计数,所以多个保存条件的效果是不会叠加


用户也可以通过设置多个SAVE选项来设置自动保存条件,


Redis关于自动持久化的配置



rdbcompression yes 创建RDB文件时,是否启用压缩
stop-writes-on-bgsave-error yes 执行BGSAVE命令时发生错误是否停止写入
rdbchecksum yes 是否对生成RDB文件进行检验
dbfilename dump.rdb 持久化生成的备份文件的名字
dir /var/lib/redis/6379 RDB文件保存的目录


例子:


1.修改Redis配置文件/etc/redis.conf



save 900 1
save 300 10
save 60 5


2.重启Redis,删除已经创建的RDB文件



[root@mysql redis]# systemctl restart redis
[root@mysql redis]# rm -rf dump.rdb
[root@mysql redis]# pwd
/var/lib/redis
[root@mysql redis]# ls
[root@mysql redis]#


3.打开redis-cli,向Redis中设置5个value



127.0.0.1:6379> flushall # 清空Redis中已有的所有数据
OK
127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> set a b
OK
127.0.0.1:6379> set c d
OK
127.0.0.1:6379> set e f
OK
127.0.0.1:6379> set g i
OK


4.查看Redis的日志记录



[root@mysql ~]# tail /var/log/redis/redis.log # 查看Redis日志的最后10行
3325:M 13 Oct 15:53:44.323 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
3325:M 13 Oct 15:53:44.323 # Server started, Redis version 3.2.10
3325:M 13 Oct 15:53:44.323 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add ‘vm.overcommit_memory = 1’ to /etc/sysctl.conf and then reboot or run the command ‘sysctl vm.overcommit_memory=1’ for this to take effect.
3325:M 13 Oct 15:53:44.323 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command ‘echo never > /sys/kernel/mm/transparent_hugepage/enabled’ as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
3325:M 13 Oct 15:53:44.323 * The server is now ready to accept connections on port 6379
3325:M 13 Oct 15:55:17.431 * 5 changes in 60 seconds. Saving…
3325:M 13 Oct 15:55:17.432 * Background saving started by pid 3349
3349:C 13 Oct 15:55:17.434 * DB saved on disk
3349:C 13 Oct 15:55:17.435 * RDB: 2 MB of memory used by copy-on-write
3325:M 13 Oct 15:55:17.534 * Background saving terminated with success


5.查看Redis的持久化文件



[root@mysql redis]# pwd
/var/lib/redis
[root@mysql redis]# ls -lah
total 8.0K
drwxr-x— 2 redis redis 22 Oct 13 15:55 .
drwxr-xr-x. 64 root root 4.0K Oct 13 13:38 …
-rw-r–r-- 1 redis redis 115 Oct 13 15:55 dump.rdb


## RDB现存问题


1.耗时耗性能


Redis把内存中的数据dump到硬盘中生成RDB文件,首先要把所有的数据都进行持久化,所需要的时间复杂度为O(N),同时把数据dump到文件中,也需要消耗CPU资源, 由于BGSAVE命令有一个fork子进程的过程,虽然不是完整的内存拷贝,而是基于copy-on-write的策略,但是如果Redis中的数据非常多,占用的内存页也会非常大,fork子进程时消耗的内存资源也会很多 磁盘IO性能的消耗,生成RDB文件本来就是把内存中的数据保存到硬盘当中,如果生成的RDB文件非常大,保存到硬盘的过程中消耗非常多的硬盘IO


2.不可控,丢失数据


自动创建RDB文件的过程中,在上一次创建RDB文件以后,又向Redis中写入多条数据,如果此时Redis服务停止,则从上一次创建RDB文件到Redis服务挂机这个时间段内的数据就丢失了


3.2 AOF(AppendOnlyFile)方式


3.2.1 AOF原理


AOF创建


当向Redis中写入一条数据时,就向AOF文件中添加一条写记录


如下图所示  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/2020112014434787.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwOTA3OTc3,size_16,color_FFFFFF,t_70#pic_center)  
 AOF恢复


Redis发生宕机重启后,**读取AOF文件对Redis中的数据进行完整的恢复,而且使用AOF文件来恢复Redis中的数据是实时**的


如下图所示  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201120144400726.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwOTA3OTc3,size_16,color_FFFFFF,t_70#pic_center)  
 3.2.2 AOF


AOF持久化保存数据库的方法是:每当有修改的数据库的命令被执行时,服务器就会将执行的命令写入到AOF文件的末尾。


因为AOF文件里面储存了服务器执行过的所有数据库修改的命令,所以Redis只要重新执行一遍AOF文件里面保存的命令,就可以达到还原数据库的目的


3.2.3 AOF安全性问题


虽然服务器执行一次修改数据库的命令,执行的命令就会被写入到AOF文件,但这并不意味着AOF持久化方式不会丢失任何数据


在linux系统中,系统调用write函数,将一些数据保存到某文件时,为了提高效率,系统通常不会直接将内容写入硬盘里面,而是先把数据保存到硬盘的缓冲区之中。


等到缓冲区被填满,或者用户执**行fsync调用和fdatasync**调用时,操作系统才会将储存在缓冲区里的内容真正的写入到硬盘里


对于AOF持久化来说,当一条命令真正的被写入到硬盘时,这条命令才不会因为停机而意外丢失


因此,AOF持久化在遭遇停机时丢失命令的数量,取决于命令被写入硬盘的时间


越早将命令写入到硬盘,发生意外停机时丢失的数据就越少,而越迟将命令写入硬盘,发生意外停机时丢失的数据就越多


3.2.4 AOF三种策略


为了控制Redis服务器在遇到意外停机时丢失的数据量,**Redis为AOF持久化提供了appendfsync选项,这个选项的值可以是always,everysec或者no**


Always



Redis每写入一个命令,always会把每条命令都刷新到硬盘的缓冲区当中然后将缓冲区里的数据写入到硬盘里。
这种模式下,Redis即使用遭遇意外停机,也不会丢失任何自己已经成功执行的数据


Everysec



Redis每一秒调用一次fdatasync,将缓冲区里的命令写入到硬盘里,
这种模式下,当Redis的数据交换很多的时候可以保护硬盘
即使Redis遭遇意外停机时,最多只丢失一秒钟内的执行的数据


No



服务器不主动调用fdatasync,由操作系统决定任何将缓冲区里面的命令写入到硬盘里,这种模式下,服务器遭遇意外停机时,丢失的命令的数量是不确定的


3.2.5 AOF三种方式比较



运行速度:always的速度慢,everysec和no都很快
always不丢失数据,但是硬盘IO开销很多,一般的SATA硬盘一秒种只能写入几百次数据
everysec每秒同步一次数据,如果Redis发生故障,可能会丢失1秒钟的数据
no则系统控制,不可控,不知道会丢失多少数据


3.2.6 AOF重写功能简介


随着服务器的不断运行,为了记录Redis中数据的变化,Redis会将越来越多的命令写入到AOF文件中,**使得AOF文件的体积来断增大 为了让AOF文件的大小控制在合理的范围,redis提供了AOF重写功能**,通过这个功能,服务器可以产生一个新的AOF文件:



新的AOF文件记录的数据库数据和原有AOF文件记录的数据库数据完全一样
新的AOF文件会使用尽可能少的命令来记录数据库数据,因此新的AOF文件的体积通常会比原有AOF文件的体积要小得多
AOF重写期间,服务器不会被阻塞,可以正常处理客户端发送的命令请求


![在这里插入图片描述](https://img-blog.csdnimg.cn/20201120145048111.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwOTA3OTc3,size_16,color_FFFFFF,t_70#pic_center)  
 AOF重写功能就是把Redis中过期的,不再使用的,重复的以及一些可以优化的命令进行优化,重新生成一个新的AOF文件,从而达到减少硬盘占用量和加速Redis恢复速度的目的


3.2 7 AOF重写触发方式


1.向Redis发送BGREWRITEAOF命令


类似于**BGSAVE命令,Redis主进程会fork一个子进程,由子进程去完成AOF重写**  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201120145104454.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwOTA3OTc3,size_16,color_FFFFFF,t_70#pic_center)  
 这里的AOF重写是将Redis内存中的数据进行一次回溯,得到一个AOF文件,而不是将已有的AOF文件重写成一个新的AOF文件


2.通过配置选项自动执行BGREWRITEAOF命令



auto-aof-rewrite-min-size


触发AOF重写所需的最小体积:只要在AOF文件的大小超过设定的size时,Redis会进行AOF重写,这个选项用于避免对体积过小的AOF文件进行重写



auto-aof-rewrite-percentage



指定触发重写所需的AOF文件体积百分比:当AOF文件的体积大于auto-aof-rewrite-min-size指定的体积,并且超过上一次重写之后的AOF文件体积的percent%时,就会触发AOF重写,如果服务器刚启动不久,还没有进行过AOF重写,那么使用服务器启动时载入的AOF文件的体积来作为基准值。
将这个值设置为0表示关闭自动AOF重写功能


只有当上面两个条件同时满足时才会触发Redis的AOF重写功能


3.2.8 AOF重写的流程  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/2020112014520015.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwOTA3OTc3,size_16,color_FFFFFF,t_70#pic_center)  
 如上图所示:


1.无论是执行bgrewriteaof命令还是自动进行AOF重写,实际上都是执行BGREWRITEAOF命令  
 2.执行bgrewriteaof命令,Redis会fork一个子进程,  
 3.子进程对内存中的Redis数据进行回溯,生成新的AOF文件  
 4.Redis主进程会处理正常的命令操作  
 5.同时Redis把会新的命令写入到aofrewritebuf当中,当bgrewriteaof命令执行完成,新的AOF文件生成完毕,Redis主进程会把aofrewritebuf中的命令追加到新的AOF文件中  
 6.用新生成的AOF文件替换旧的AOF文件


3.2.9 配置文件中AOF相关选项



appendonly no # 改为yes,开启AOF功能
appendfilename “appendonly.aof” # 生成的AOF的文件名
appendfsync everysec # AOF同步的策略
no-appendfsync-on-rewrite no # AOF重写时,是否做append的操作
AOF重写非常消耗服务器的性能,子进程要将内存中的数据刷到硬盘中,肯定会消耗硬盘的IO
而正常的AOF也要将内存中的数据写入到硬盘当中,此时会有一定的冲突
因为rewrite的过程在数据量比较大的时候,会占用大量的硬盘的IO
在AOF重写后,生成的新的AOF文件是完整且安全的数据
如果AOF重写失败,如果设置为no则正常的AOF文件中会丢失一部分数据
生产环境中会在yes和no之间进行一定的权衡,通过优先从性能方面进行考虑,设置为yes
auto-aof-rewrite-percentage 100 # 触发重写所需的AOF文件体积增长率
auto-aof-rewrite-min-size 64mb # 触发重写所需的AOF文件大小


3.2.10 Redis的AOF功能示例


1.打开一个Redis客户端



[root@mysql ~]# redis-cli
127.0.0.1:6379> config get appendonly # 查看appendonly配置项结果

  1. “appendonly”
  2. “no”
    127.0.0.1:6379> config set appendonly yes # 设置appendonly选项为yes
    OK
    127.0.0.1:6379> config rewrite # 把配置写入到文件中
    OK
    127.0.0.1:6379> config get appendonly # 再次查看appendonly选项结果,看修改是否写入到配置文件中
  3. “appendonly”
  4. “yes”
    127.0.0.1:6379> set hello world
    OK
    127.0.0.1:6379> set hello php
    OK
    127.0.0.1:6379> set hello python
    OK
    127.0.0.1:6379> incr counter
    (integer) 1
    127.0.0.1:6379> incr counter
    (integer) 2
    127.0.0.1:6379> rpush list a
    (integer) 1
    127.0.0.1:6379> rpush list b
    (integer) 2
    127.0.0.1:6379> rpush list c
    (integer) 3
    127.0.0.1:6379> dbsize # 查看Redis中数据量

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

(integer) 1
127.0.0.1:6379> incr counter
(integer) 2
127.0.0.1:6379> rpush list a
(integer) 1
127.0.0.1:6379> rpush list b
(integer) 2
127.0.0.1:6379> rpush list c
(integer) 3
127.0.0.1:6379> dbsize # 查看Redis中数据量

[外链图片转存中…(img-4vf2RafB-1715489485739)]
[外链图片转存中…(img-onF150KQ-1715489485740)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值