Redis持久化(RDB/AOF)

Redis持久化(RDB/AOF)_第1张图片

"在哪里走散,你都会 找 到 我。" 


认识持久化

        我们在接触Mysql事务的时候,一定了解过Mysql事务的四个特性:
        "原子性(A)一致性(C)隔离性(I)持久性(D)"

        而其中持久性其实与持久化是一回事,所谓持久与不持久,针对的是数据。如果将该数据存储在磁盘上,那么数据就具有持久性,反之如果数据仅仅存在于内存上,就不具有持久性。

redis持久化:

        对于Redis而言,是一个内存数据库,操作的数据大都是内存级别的(Redis相比于Mysql明显优势和 特点)。但在内存存储数据是不持久的,一旦断电内存中的数据就会被清空,要想持有持久化的特性,数据必须存储在磁盘上。

        所以,既要保证速度快,那么数据的操作一定还是在内存,但如果要保证持久化,数据还是得想办法存储在磁盘上。Redis决定全都要!

Redis持久化(RDB/AOF)_第2张图片

        可是内存与硬盘上存储的数据只是存在理论上的一致性,实际中可能存在一定的偏差,这同我们选择的 "持久化策略" 是息息相关的。 

内存 or 硬盘?

        也许你就会有疑问,如果此时要想redis插入或者获取一个数据,是在内存、是硬盘上操作呢?

         当要插入一个数据时,就需要把这个数据同时写入内存、硬盘之中的!但说是这样说,何时写入硬盘,效率咋样,都是同我们选择的策略有关的。

        如果是要查询一个数据,直接选择从内存中读取即可。硬盘数据仅仅是在redis进入重启时,用来恢复原来内存中数据的。  


Redis持久化策略

        严格来说redis中的持久化策略有两种:

● RDB -- Redis DataBase

● AOF -- Append Only File

        其中你可以把RDB策略理解为一种"定期备份",它一定带来的一个问题是实际内存值与备份值可能存在偏差。AOF策略可以理解为一种“实时备份”。

(1) RDB简介

        RDB持久化就是将当前进程中的数据,定期写入到磁盘中,生成所谓的“快照”,也是Redis默认的持久化机制。

触发方式:        

● 手动触发        

        程序猿通过redis客户端执行特定的命令,触发生成快照。

save: 执行save命令时,会导致redis全力以赴生成“快照”,因为redis采用的是单线程模型,此时就会阻塞redis处理其他客户端的命令。(出现类似keys*的后果,一般不建议使用save)。

bgsave: 不会影响redis处理其他客户端的命令。但,redis咋做到不需要多线程完成并发编程的?答案是这里使用的是多进程模型,来处理并发编程。

● 自动触发  

        在Redis配置文件中设置了让Redis,每隔多长时间生成\每产生多少次修改,就会触发生成快照。

RDB文件

        redis的配置文件通常会在/etc目录下的redis.conf文件。        Redis持久化(RDB/AOF)_第3张图片

        我们打开redis.conf文件后,可以找到redis生成的rdb文件是存放在redis的工作目录中的,这个是可以在redis中进行配置的。 

Redis持久化(RDB/AOF)_第4张图片

        我们进入这个路径就可以看到这文件名为 "dump.rdb"的文件。        Redis持久化(RDB/AOF)_第5张图片

        当我们打开这个文件时,我们会发现是一堆乱码。        

Redis持久化(RDB/AOF)_第6张图片

        dump.rdb本质是一个二进制文件,是将内存中的数据,以压缩的形式保存在这个二进制文件之中的。我们一定不要拿着vim,将把这个rdb文件里的内容进行乱改。因为redis每次重启都会尝试加载这个rdb文件,如果发现这个文件格式是错误的,数据加载也会出现错误。        Redis持久化(RDB/AOF)_第7张图片

Redis持久化(RDB/AOF)_第8张图片

        当然,我们认为不去修改并不是唯一可能导致rdb文件出现损坏的情况,当把rdb文件进行网络传输,仍然可能造成内容缺失,引起文件破坏,此时可能导致redis服务器无法启动。        

        redis还提供了rdb文件检查工具~        Redis持久化(RDB/AOF)_第9张图片        Redis持久化(RDB/AOF)_第10张图片                

RDB触发流程        

        当执行生成rdb文件镜像时,此时会先将要生成的快照数据保存在一个临时文件之中。当这个快照生成完毕后,会删除之前的rdb文件,并把这个临时文件重命名为dump.rdb,因此从始至终都只有一份rdb文件。        Redis持久化(RDB/AOF)_第11张图片

 

rdb触发时机      Redis持久化(RDB/AOF)_第12张图片

        rdb文件的数据,不会根据你简简单单插入一些数据就会发生更改。其原因就在于没有触发RDB机制。

自动触发:      

        在前些段落提到过rdb有两种触发机制,分别是自动和手动触发。自动触发机制主要是在配置文件中,需要去手动进行修改。        Redis持久化(RDB/AOF)_第13张图片

        当然,这些值不能设置得过小,导致频繁触发生产快照,而每一次快照生成的成本也不是可以忽略的。正因为不能频繁生成快照,所以rdb文件里的数据与实时数据可能会存在偏差。

        甚至,如果redis服务器直接挂掉(例如使用kill命令等)。会导致在上一个快照版本,与服务器崩掉前期间的数据都丢掉了!这不是rdb能够解决的问题。

 
手动触发:

        手动执行命令save\bgsave,因为咱们的数据量是很少的,所以一旦执行这两个命令中的其中一个都会很快的产生结果。感受子进程创建的过程,对我们来说比较奢望,但是检查生成的新文件,对我们而言却十分容易。

        Linux文件系统是基于ext4的组织方式,将文件系统分为三大组成部分:
▪ 超级块:放的是一些管理内容。

▪ inode区: 存放inode节点,每一个文件都有唯一的inode数据结构进行对应。

▪ block区:存放文件的数据内容。

        所以,判断一个文件是否被替换,就检查它的inode即可。        Redis持久化(RDB/AOF)_第14张图片

 

RDB的优缺点

• RDB是⼀个紧凑压缩的⼆进制⽂件,代表Redis在某个时间点上的数据快照。

• Redis加载RDB恢复数据远远快于AOF的⽅式。RDB使用二进制的方式来组织数据,直接把数据读取到内存中来,按照字节格式取出来即可。但是AOF是用文本方式来组织数据,需要一系列的字符串切分操作。

• RDB⽅式数据没办法做到实时持久化/秒级持久化。因为bgsave每次运⾏都要执⾏fork创建⼦进程,属于重量级操作,频繁执⾏成本过⾼。

• RDB⽂件使⽤特定⼆进制格式保存,Redis版本演进过程中有多个RDB版本,兼容性可能有⻛
险。

        当然RDB最大的问题还是在于,无法实时持久化保存数据,在两次快照之间,如果服务器出现差错,数据会出现丢失。

(2) AOF简介

        AOF(AppendOnlyFile)持久化:以独⽴⽇志的⽅式记录每次写的命令,重启时再重新执⾏AOF⽂件中的命令达到恢复数据的⽬的。        

        “AOF的主要作⽤是解决了RDB数据无法持久化的问题”。

使用AOF

        因为redis默认使用将RDB作为默认的持久化机制,开启AOF功能需要设置配置:

Redis持久化(RDB/AOF)_第15张图片

        该appendonly.aof文件同rdb文件一样,存在于工作目录。

AOF文件        Redis持久化(RDB/AOF)_第16张图片

        AOF本质上是一个文本文件,可以类似于Mysql中的binlog,记录用户的一系列操作。其中会用到一些特殊符号作为分隔符。

        

AOF触发流程

Redis持久化(RDB/AOF)_第17张图片

▪ 手动触发:

        调⽤bgrewriteaof命令

▪ 自动触发:

        根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数确定⾃动触发时
机。

Redis持久化(RDB/AOF)_第18张图片

auto-aof-rewrite-percentage:代表当前AOF占⽤⼤⼩相⽐较上次重写时增加的⽐例.

auto-aof-rewrite-min-size:表⽰触发重写时AOF的最⼩⽂件⼤⼩,默认为64MB.

AOF介入

        对于RDB而言,生成的快照只是对当前内存中数据的一份镜像,它一定存在数据不具有实时性的问题。由此,引入AOF后,既需要对内存进行写入,又需要对磁盘进行写入,才能保证数据的实时性。这会产生一个问题:

AOF策略是否会严重影响到Redis处理请求的速度?

        答案是否定的!

        AOF的工作机制并非把工作线程的数据直接就写在磁盘上,而是会在内存中开辟空间,用作缓冲区,在积累了一波后,才会向硬盘统一写入这一份数据。     

        硬盘内容的读取是根据磁头寻址的方式,如果内容数据是随机地址,那么查询花费的时间是很高的,效率也是低下的。相反,如果是顺序写入,磁头的读取效率是比随机读取要高很多的(虽然仍比不过内存的读取速度)。

        AOF是把每次新的操作写入到原文件的末尾,这是顺序写入。        

AOF策略

        将数据写入在内存开辟的缓冲区中,其数据存储还是在内存中的,一旦断电、或者崩溃这些数据还是会发生丢失!这是不可避免的!

        redis为程序猿给出了一些选项,也就是一些刷新策略(缓冲区)。

        

可配置项 说明
always 命令写入aof_buf后,调用fsync同步,完成后返回
everysec 命令写入aof_buf后,只执行write操作,不进行fsync。由同步线程每秒进行fsync
no 命令只执行aof_buf,由OS控制fsync频率

        我们谈到访问外设速率,并不强调访问或读取速度,而是次数。

▪ 当刷新频率越高,对性能影响越大,同时数据的可靠性越高。

▪ 当刷新频率越低,对性能影响越小,同时数据的可靠性越低。

Redis持久化(RDB/AOF)_第19张图片

AOF重写机制

        随着命令不断写⼊AOF,⽂件会越来越⼤。

Redis持久化(RDB/AOF)_第20张图片        较⼩的AOF⽂件⼀⽅⾯降低了硬盘空间占⽤,⼀⽅⾯可以提升启动Redis时数据恢复的速度。

AOF重写流程                              

Redis持久化(RDB/AOF)_第21张图片

● 如果当前进程正在执⾏AOF重写,又接收到AOF请求直接返回。如果是当前进程正在执⾏bgsave(RDB)操作,重写命令延迟到bgsave完成之后再执⾏。

● ⽗进程执⾏fork创建⼦进程。

● 重写

        1.主进程fork之后,继续响应其他命令。所有修改操作写⼊AOF缓冲区并据appendfsync策略同步到硬盘,保证旧AOF⽂件机制正确。 如果重写中断,能够恢复出原数据。

        2.⼦进程只有fork之前的所有内存信息,⽗进程中需要将fork之后这段时间的修改操作写⼊
AOF重写缓冲区中。从而保证数据的实时性。

● ⼦进程根据内存快照,将命令合并到新的AOF⽂件中。

● ⼦进程完成重写

        1.新⽂件写⼊后,⼦进程发送信号给⽗进程。

        2.⽗进程把AOF重写缓冲区内临时保存的命令追加到新AOF⽂件中。

        3. ⽤新AOF⽂件替换⽼AOF⽂件。

(3) 混合持久化

        顾名思义,混合持久化要做的既是要保证实时性,又得保证效率。结合aof和rdb的特点。

Redis持久化(RDB/AOF)_第22张图片

        按照aof的方式,对每一个请求、操作都记录到文件里,触发aof重写后,就会把内存的当前状态形成快照,按照rdb的存储格式写入到aof新文件里。后续再进行操作,会按照aof文本的方式追加到文件后面。

 


 

AOF vs RDB

        当redis启动时,会根据aof或者rdb文件进行数据恢复。但,如果两者文件都存在,那么redis会如何选择呢?        Redis持久化(RDB/AOF)_第23张图片     

        rdb对于fork之前的数据会进行备份,但对于fork之后的数据则会置之不理,不会关心之后的任何数据。而对于aof,关心fork之前的数据意外,还能通过aof_rewrite_buf换从化区获取fork之后新数据。

        rdb本身的设计理念是“定期备份”,而aof设计的理念在于“实时备份”。


● RDB视为内存的快照,产⽣的内容更为紧凑,占⽤空间较⼩,恢复时速度更快。但产⽣RDB的开销较⼤,不适合进⾏实时持久化,⼀般⽤于冷备和主从复制。

● AOF视为对修改命令保存,在恢复时需要重放命令,持久性安全性高。并且有重写机制来定期压缩AOF⽂件。但其加载速度是不及RDB的。

● RDB和AOF都使⽤fork创建⼦进程,利⽤Linux⼦进程拥有⽗进程内存快照的特点进⾏持久化,尽可能不影响主进程继续处理后续命令。
 


本篇到此结束,感谢你的阅读。

祝你好运,向阳而生~

Redis持久化(RDB/AOF)_第24张图片
        

你可能感兴趣的:(redis,redis,数据库,缓存)