写在前面:
开这个系列是希望随着自己的学习成长尝试总结一些容易有坑或理解上可能有一定难度的课题,期许其他有兴趣的同学阅读能够直观的理解并快速掌握;所以本系列主要目标读者为Redis入门或非技术同学,其他资深同学如已有一定理解,可以直接略过;该系列中任何讲解不当之处欢迎指正。
Redis本身作为一个内存KV Store,本篇暂不探讨其性能如何强劲,而是从数据容灾的高可用高安全需求切入,高可用的实现及分析请参考 Redis探寻(第一话)Redis公网常见架构与阿里云架构对比 ,第二话咱们主要分析其高安全实现,即持久化(备份)机制。
提到持久化首先必须提到这样几个关键词:AOF,RDB,FORK,COW,BGSAVE,BGREWRITEAOF,很多同学可能会对这几个词很困惑,不急,下面通过几个简单的小例子给你讲清楚。
一、引入
首先,我们先假设刘小强同学开了个’神奇‘的停车场,这个停车场只停同一厂家的同一款车,除了牌号不一样啥都一样,刘小强同学承接的还是五星级酒店的代泊车业务,需要人工登记哪个牌号的车开进了哪个车位这种记录,如下图1,假如车位就是Key,对应牌号的车就是Value,下面我们就用刘小强同学的停车场给大家解释Redis的持久化机制
二、快照(RDB)持久化
2.1 RDB概念
RDB方式是通过快照方式完成的,当符合一定条件时Redis会自动将内存中的所有数据进行快照并且存储到硬盘上。进行快照的条件在配置文件中指定,有2个参数构成:时间和改动键的个数,当在指定时间内被更改的键的个数大于指定数值时就会进行快照。RDB是Redis默认的持久化方式。
2.2 RDB触发条件
- save 900 1 # 15分钟内至少有一个键被更改
- save 300 10 # 5分钟内至少有10个键被更改
- save 60 10000 # 1分钟内至少有10000个键被更改
2.3 RDB实现方式
- Redis调用fork(),产生一个子进程。
- 子进程把数据写到一个临时的RDB文件。
- 当子进程写完新的RDB文件后,把旧的RDB文件替换掉。
2.4 刘小强的小故事A
刘小强同学看着停车场车来车往很是欣慰,忽然转念一想,不对,假如我停车场地震了或者我本子太多丢了一本,我怎么确认当初每个车位停的是哪个车呢,停车的都是上帝,我得保证上帝的利益不受损失;于是,刘小强同学买了个无人机,旁边开了个一样大的临时停车场,又雇了个打零工的Fork同学,新同学做什么呢?
- 15小时内至少有1个车位车子有变动
- 5小时内至少有10个车位车子有变动
- 1小时内至少有10000个车位车子有变动
只要符合上面三个条件任意一个,这个Fork同学就会去开无人机把停车场拍一遍,然后在临时停车场直接对应车位放上车再上个对应牌子(请忽略刘小强同学危险的套牌行为!),然后拿个小本子开始如下图2一样抄写,抄写完毕后把这个新的小本子给刘小强同学锁进保险箱,除非Fork同学下次再写一本新的小本子,刘小强才会把现在这本扔掉再把新的放进去。
2.5 小故事A的理解方式
这里的停车场就是Redis的内存,车位和车牌的对应关系就是KV对应关系;
COW(Copy On Write)就是刚刚Fork同学的整个操作(子线程开新内存区域复制原有内存,COW是Linux的内存特性);
FORK对应的就是Fork同学(主线程外起子线程,不干扰主线程业务);
BGSAVE对应的就是Fork同学抄写小本子并保存的操作(记录Fork子线程复制的内存区域内的KV对信息)
所以我们就可以理解RDB持久化的几个特点:
- BGSAVE过程中需要和已使用内存相同大小的额外内存,如内存不足使用虚拟内存效率会明显降低(需要临时停车场)
- RDB备份文件不能保证备份数据的实时性,往往有较大延迟;(Fork同学两次写小本子时间差内,甚至某次写小本子时,刘小强同学停车场可能已经出入了无数次车了,这些出入结果不能实时保障)
三、追加式(AOF)持久化
3.1 AOF概念
Redis的AOF持久化策略是将发送到Redis服务端的每一条命令都记录下来,并且保存在硬盘的AOF文件中。可以通过参数appendonly来设置是否启用AOF。AOF文件的位置和RDB的位置相同,都是通过dir参数设置,默认的文件名是appendonly.aof,可以通过appendfilename参数修改。
3.2 AOF同步策略
文件写入默认情况下会先写入到系统的缓存中,按策略设置,系统每隔一定时间同步一次。
- appendfsync always 每次都同步(最安全但是最慢)
- appendfsync everysec 每秒同步(默认的同步策略)
- appendfsync no 不主动同步,由操作系统来决定(最快但是不安全)
3.3 AOF重写策略
当前的AOF文件大小超过上一次重写的AOF文件大小的百分之多少时会再次进行重写,如果之前没有重写过,则以启动时的AOF大小为依据。
- auto-aof-rewrite-percentage 100
3.4 刘小强的小故事B
刘小强同学在之前的RDB方式记小本子确实发生了停车场地震这种惨绝人寰的灾难,更惨的是由于记录不是最新的,刘小强同学被一些已经开出停车场的车主恶意索赔,多赔了好大一笔钱,现在,刘小强同学痛定思痛,决定东山再起;当然,他也决定改变车辆出入记录的方式;刘小强发现原来的自己的小本子是最实时的,但是量太大了,往往要记很多小本子,那怎么样能保证自己永远只记一本本子,万一再地震随时拿着这一本本子跑呢?同时临时工Fork同学既然雇了,人家毕竟跟自己患难与共了,赶人家走也不好;忽然,刘小强同学灵机一动,想出了这样的法子:
刘小强同学的本子有1000页,他决定,每当他记到800页的时候,就让Fork同学再耍起无人机,去临时停车场套牌,然后再拿一个和刘小强一样的新的小本子从头按下面图3的方式重新记笔记
此时,刘小强同学仍然正常接待车辆进出,并将记录记在最后这200页上,直到Fork同学把记完的新本子给到刘小强同学,刘小强同学立即挂出’暂停营业‘的牌子,同时开始在Fork同学的小本子后面开始把旧本子最后200页的进出记录逐条加上去,如图4所示
刘小强同学把记录全部写上后,立刻扔掉旧本子,撤掉’暂停营业‘的牌子,继续允许车辆进出,并且把进出记录在新本子上继续往下记;一旦新本子有写到800页,立刻重复上面流程;从此刘小强同学的停车场虽然陆续又遇到了好几次地震,但他都靠着这个’神奇‘的小本子合理的赔偿客户,即便有一两个因为自己忙地震时没及时记下的车主闹腾,他也完全扛得住了,可喜可贺!
3.5 小故事B的理解方式
这里仍然用到了COW和FORK,不多做赘述;
BGREWRITEAOF操作就是Fork同学记小本子的过程,和BGSAVE不同的是Fork同学记录的方式有变化,记录项更多了。
AOF持久化BGREWRITEAOF完成后在新小本子里面补记录时会停止营业,记录补完才会继续恢复营业(Redis节点上表现为瞬时性的阻断新请求)
所以,AOF持久化的几个特点:
- AOF文件往往比RDB文件更大(AOF小本子记录内容更繁杂)
- AOF文件重写过程中如果因为业务流量大等极端情况容易出现连接阻断情况
- AOF文件一般默认每秒同步(刷盘),故障时一般只丢失秒级操作数据(地震来得太快刘小强同学来不及记小本子)
到此,RDB和AOF持久化机制基本讲清楚了,如果还有疑问欢迎钉钉咨询 玉圭 。感谢多灾多难的刘小强同学!
刘小强小课堂:RDB和AOF文件灾备恢复时哪个更快?
Answer:不妨这样问自己,某次地震后重建时,刘小强同学预先套好牌后,由大型运输机统一批量空投车辆到对应车位快,还是刘小强同学让人逐一从停车场外开进对应车位快!