第五课补充01——持久化

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第五课补充01——持久化相关的知识,希望对你有一定的参考价值。

1、 多数据库,默认16个库;默认在0库;

2、 2种持久化机制:rdb(快照模式)、aof(日志模式)

(1) rdb持久化,2种方式:手动命令save和后台save

手动命令save会阻塞客户端的进程请求,直到save执行完成,因为redis本身是单线程的执行方式;

bgsave方式保存,是fork一个子进程来执行数据保存,

 

技术分享 

技术分享 

 

fork出的子进程进行bgsave的同时,父进程继续处理客户端的新请求,因此就涉及到新数据同步问题;父进程和子进程之间通过copy on write机制进行数据同步(主进程的数据量被子进程的数据量不一致时,才会copy on write)。

 

子进程是将数据写入到一个临时文件,然后通过原子性rename系统调用将临时文件重命名为rdb文件,因此,在任何时候出现故障,redis的rdb文件都是可用的。

持久化是写入磁盘,对磁盘IO影响比较大;

Redid支持rdb和aof一起持久化,但是调用bgsave命令或bgrewriteaof命令,同时只能有一个在执行,redis在执行存盘命令时,会检测当前是否已经有bgsave或bgrewriteaof在执行;

 

【测试——rdb快照模式】

RDB文件是二进制的,所以并不存在回车换行来分隔一行一行

1、 手动方式save命令保存数据到磁盘:

初,redis库里无数据,dump.rdb文件内容如下:

技术分享 

技术分享 

技术分享 

执行set命令设置键值,此时没执行save命令,dump.rdb文件大小依旧为18Mredis日志没有记录;

技术分享 

技术分享 

技术分享 

技术分享 

技术分享 

【总结】

只有执行save命令OK,才将redis数据写入磁盘

 

【测试——rdb模式,手动bgsave

紧接着如上测试

初,

技术分享 

技术分享 

只执行set命令设置键值,没有保存,数据存放在缓存,没写入磁盘,因此此时dump.rdb文件大小不变

技术分享 

执行bgsave命令和save命令的返回值不同,save命令是在当前线程下执行,会阻塞客户端其他请求的执行;bgsave返回:Background saving started,是fork一个子进程来执行数据保存,不会阻塞客户端其他请求的执行;

技术分享 

Dump.rdb文件大小增长,说明执行bgsave后,将数据保存到磁盘

技术分享 

对比save命令和bgsave命令所产生的日志文件也可以看出:bgsave命令作为后台执行的命令,fork一个子进程(进程号为30543)将数据保存到磁盘;

日志RDB: 6 MB of memory used by copy-on-write表示:redis借助fork命令的copy on write机制(私有内存非共享内存),在生成快照时,将当前进程fork出一个子进程,然后在子进程中循环所有的数据,将数据写成为RDB文件。这个过程消耗6MB内存。

 

【测试——rdb模式,配置文件设置保存触发条件】

紧接着上面测试

技术分享即,120秒内变化1次,就自动执行bgsave

初,

技术分享 

技术分享 

等候120秒后,查看dump.rdb文件大小和日志

技术分享 

技术分享 

配置文件配置的自动保存和bgsave命令区别在于,会根据配置的触发条件,本次测试的是120秒内改变1次就保存,当满足触发条件,就fork一个子进程执行bgsave命令;

在紧接着上面测试,测试2个以及2个以上触发条件如何处理?当满足第一个条件后,第二个save条件是否会重新计时??
技术分享

初,

技术分享 

120s内change 1次的日志:

技术分享 

60s内change 2次的日志:

技术分享 

60s内change 1次,61s到120内再change 1次的日志:

技术分享 

 

60s内change 2次,61s到120内再change 1次的日志:

技术分享 

【总结】

对于技术分享这个配置下,redis里的周期函数serverCron每隔0.1s执行一次,当在60秒内检测到数据改变次数达到两次了,就会执行一次bgsave。每次写盘后,记录写盘时间,以及保存数据库发生多少次操作。重新计时(因此我在60秒的前20秒内执行完第二次change,数据就被刷到磁盘了

61s120s直接change一次,因为周期检测,没在60s内检测到数据改变2次(以上),不满足save 60 2条件,转而检测是否满足save 120 1,因此在我change后,满足1次修改,就直接刷入磁盘。

总结计时,save参数设置后,redis的周期函数serverCron会周期性检测,从时间范围短、操作频繁的save条件开始检测,一旦检测到满足就立刻执行bgsave;不满足,则转而检测时间次长、操作次频繁的save条件。。。。

 

 

技术分享 

建议stop-writes-on-bgsave-err false,就是bgsave出错时,前面请求继续,这样就是业务优先;

Dir ./rdb文件或者aof文件的存储目录,如果同时采用两种持久化机制,磁盘竞争比较大;默认情况下rdb是开启的,想关闭rdb持久化,把save参数注销就可以了;

技术分享 

 

技术分享 

AOF存储格式:

Aof持久化方式,存储文件是根据数据库里的key,每个key生成一条日志,也就是不管执行多少次中间值变化,aof文件只存储最后的键值;

技术分享 

 

技术分享 

技术分享 

默认情况下是每秒刷入一次磁盘;

Always策略:一有变化就写入磁盘,数据丢失少,磁盘IO压力大;

技术分享技术分享 

 

技术分享 

Rdbaof同时启用时,redis在加载数据前,优先加载aof文件

技术分享 

技术分享 

技术分享 

客户端执行aofrewriteaof重写命令后,会将命令同时发送到AOF缓冲区和AOFc重写缓冲区;

(1) aof缓冲区,存储执行重写命令产生的数据。也即是将键值保存成命令形式,先放在oaf缓冲区,再根据触发刷新到磁盘;

(2) aof重写缓冲区,是存储在重写过程中,客户端执行的新的命令。在子进程执行重写aof操作的过程中,父进程继续处理客户端发来的命令,同时将客户端的命令发生到aof重写缓冲区,等重写aof完成后,直接将aof重写缓冲区的命令直接追加到重写后的aof文件后面,这样保证整个重写过程的数据完整性;

技术分享 

技术分享 

1AOF重写,不会读取当前的aof文件,而是直接读取内存,将内存里的键值转换为命令,存在一个新的aof文件里;在重写过程中,会将客户端发来的命令存放在aof重写缓存里,aof重写结束后,将重写缓存里保存的命令追加到新生成的aof文件里;

2)对于list这种会有很多元素的类型值,为了避免重写导致客户端输入缓冲区内存溢出,当处理列表  哈希表 集合 有序集合时,如果长度超过64个,则分成多个命令执行,64个通常是redis.h/REDIS_AOF_REWRITE_PER_CMD配置;

 





以上是关于第五课补充01——持久化的主要内容,如果未能解决你的问题,请参考以下文章

PHP & MySQL数据库专题 第五课 数据查询

PHP & MySQL数据库专题 第五课 数据查询

第五课-第一讲05_01_egrep及扩展正则表达式

2018-08-22 第三十五课

第五课-第二讲05_02_bash脚本编程之一 变量变量类型等

第五章:Python 之 RabbitMQ消息持久化