首页 快讯正文

南通招聘网:详细分析Redis的持久化操作——RDB与AOF

admin 快讯 2020-04-26 123 0

一、前言

  由于疫情的缘故原由,学校还没有开学,这也就让我有了许多的时间。趁着时间对照多,我终于可以最先学习那些之前一直想学的手艺了。最近这几天最先学习Redis,买了本《Redis实战》,看到了第四章,前三章都是讲一些Redis的基本使用以及下令,第四章才最先涉及到原理相关的内容。《Redis实战》的第四章涉及到了Redis的持久化、主从复制以及事务等内容,我个人认为这些应该属于Redis中对照主要的部门,也是面试的常考内容。这篇博客就来纪录一下Redis的持久化机制。


二、正文

2.1 为什么需要持久化

  学习过Redis的应该都知道,RedisMySQL等关系型数据库差别,它的数据不是存储在硬盘中,而是存放在内存,以是Redis的速率异常快。而这也就会造成一个问题电脑若是宕机,或者由于某些缘故原由需要重启,此时内存中的数据就会丢失Redis既然把数据存放在内存,自然也就无法制止这个问题。以是,为了在电脑重启后,能够恢复原来的数据,Redis就需要提供持久化的机制,将Redis数据库存储在内存中的数据,在磁盘中举行备份,也就是持久化。而当Redis重启后,去磁盘中将持久化的数据重新读取到内存,便能制止数据的丢失。


2.2 Redis的持久化方式

  Redis提供了两种持久化的方式,分别是:

  • 快照持久化;
  • AOF持久化;

  下面我就来详细地先容这两种持久化的方式。


2.3 快照持久化(RDB)

  快照持久化也就做RDB持久化。快照持久化的实现方式简朴来说就是:Redis将当前内存中存储的数据写入到一个文件中,将这个文件作为Redis当前的一个快照,保留在磁盘中。当Redis重启时,将这个快照文件中存储的内容加载进内存,即可恢复Redis之前的状态。默认情况下,Redis将快照保留在一个叫做dump.rdb的文件中,我们也可以在设置文件中,通过dbfilename选项来设置快照文件的名称;默认情况下快照文件就保留在Redis的安装目录下,我们可以在设置文件中,通过dir选项来设置快照文件的存储路径(实在也是AOF的路径)。


2.4 执行快照持久化的方式

  执行快照持久化有两种方式:

2.4.1 使用设置文件

  第一种方式就是在Redis的设置文件中(windows下这个文件叫redis.windows-service.conf)加上save设置项,好比像下面这样:

save 60 100:在设置文件中加上这一条的意思是,Redis会每60秒检查一次,若在这60秒中,Redis数据库执行了100次以上的写操作,那Redis就会天生一个快照文件,替换原来的快照文件;若不知足这个条件,则不天生快照,继续守候60秒;

  我们可以凭据自己的需求,调整每次守候的时间,以及对写操作次数的要求。而且,我们可以在设置文件中,添加多个save选项,好比一个save 60 100,一个save 5 10,则Redis5秒以及每100秒都市判断一次。需要注重的是,我们不应该让天生快照太过频仍,由于这是一个对照消耗资源的事情,会降低Redis的响应速率。


2.4.2 使用指令

  执行快照持久化的第二个方式就是使用Redis指令,Redis提供了两个指令来请求服务器举行快照持久化,这两个指令分别是SAVEBGSAVE

(a)BGSAVE指令

  BGSAVE的执行流程如下:

  1. Redis挪用系统的fork(),建立出一个子历程;
  2. 子历程将当前Redis中的数据,写入到一个临时文件中;同时父历程不受影响,继续执行客户端的请求;
  3. 子历程将所有的数据写入到了临时文件后,于是使用这个文件替换原来的快照文件(默认是dump.rdb);

  值得一提的是,通过设置文件执行快照持久化的方式,现实上就是Redis在判断知足条件时,挪用BGSAVE指令来实现的。

(b)SAVE指令

  SAVE指令天生快照的方式与BGSAVE差别,Redis执行SAVE指令时,不会建立一个子历程,异步的天生快照文件,而是直接使用Redis当前历程。执行SAVE指令在建立快照的历程中,Redis服务器会壅闭所有的Redis客户端,直到快照天生完毕,并更新到磁盘之后,才会继续执行客户端发来的增删改查的指令。

  固然,这个指令一样平常很少使用,由于会壅闭客户端,造成停留。然则现实上,这个指令的执行效率一样平常比BGSAVE更高,由于不需要建立子历程,而且在这个历程中,其他操作被壅闭,Redis服务器一心一意地天生快照。在《Redis实战》中,作者提到了使用SAVE指令的一个案例:

  当前服务器的Redis数据库中保留了大量数据,使用BGSAVE指令天生快照会异常的耗时 ,而且由于所剩内存不多,甚至无法建立子历程,于是作者编写了一个shell剧本,这个剧本的内容就是让服务器天天破晓3点,执行SAVE下令,天生快照,这样就不需要建立子历程,而且由于是破晓三点,用户较少,SAVE的壅闭机制也不会有太大的影响。


2.5 快照持久化的优瑕玷

(1)优点:

  1. 快照的rdb文件是一个经由压缩的紧凑文件,它保留了Redis在某个时间点上的数据集,这个文件异常适合用来备份。我们可以存储Redis服务器在差别时间点上的rbd文件,好比说一小时存储一次,一个月存储一次,这样就可以在遇到问题或有特殊需求时,将Redis恢复到某一个时间点;

  2. RDB异常适用于灾难恢复(disaster recovery):它只有一个文件,而且内容都异常紧凑,可以(在加密后)将它传送到其余服务器上;

  3. RDB 可以最大化 Redis 的性能:父历程在保留 RDB 文件时唯一要做的就是 fork 出一个子历程,然后这个子历程就会处置接下来的所有保留事情,父历程无须执行任何磁盘I/O操作,以是不会影响父历程处置客户端的请求;

  4. RDB 在恢复大数据集时的速率比 AOF 的恢复速率要快。

(2)瑕玷

  1. 当我们的服务器发生异常,导致停机时,那我们将会丢失最后一次建立快照后,所作的所有写操作,由于这些操作发生在内存中,还没来得及同步到磁盘。好比我们在设置文件中设置每5分钟天生一次快照,那当系统发生故障导致宕机时,我们将会丢失好几分钟内的操作;
  2. 每次执行BGSAVE建立快照,都需要先建立出一个子历程,再由子历程执行后续操作,当内存中数据较大时,建立一个子历程将会异常耗时,造成服务器守候数毫秒,甚至到达一秒,影响用户体验。而且从这一点也可以说明,我们不能通过提高天生快照的频率,来解决第一个瑕玷;

2.6 AOF持久化

  AOF全称为只追加文件(append-only file),它的实现方式简朴来说就是:AOF持久化机制,会将Redis执行的所有写指令,追加到到AOF的末尾,当服务器发生宕机,或者由于某些缘故原由需要重启时,在重启后,读取AOF文件,重新执行其中纪录的写操作,以此到达恢复数据的目的。

  AOF持久化机制默认是关闭的,我们可以在设置文件中,设置appendonly yes来开启。同时我们也可以通过设置appendfsync,控制写操作追加到AOF中的频率,它有如下三种选项:

  • alwaysRedis每次执行写指令,都市立即将这个写指令同步到AOF中;使用这个选项时,Redis发生异常,则最多只会丢失一次写操作(也就是在同步的历程中宕机,没同步完成),然则这也会导致Redis的响应速率变慢,由于此选项会造成频仍的IO操作;
  • everysec(默认):每秒同步一次,使用此选项,速率足够快,而且发生宕机时也只会丢失1s内的写操作;
  • no:让操作系统来决议什么时候举行同步,这个选项速率更快,然则不安全,宕机时丢失数据的若干是不确定的;

  推荐(也是默认),使用第二个选项everysec,每秒举行一次同步,由于这个选项兼顾了速率与安全性,而第一个选项太慢,第三个选项无法保证安全性。


2.7 AOF的重写机制

  AOF持久化的执行机制就是,不断地将写指令追加到AOF的末尾,这样就会导致AOF越来越大。为了解决AOF越来越大的问题,Redis实现了一种优化机制——AOF重写。当Redis检查到AOF已经很大时,就会触发重写机制,优化其中的内容,将它优化为能够获得相同效果的最小的指令聚集。

  好比说,我们在Redis中使用SET指令建立了一个String类型的数据,最后使用DEL指令将它删除了。若是开启了AOF持久化,那么则AOF中,将会纪录这条SETDEL指令。然则,在执行重写的历程中,这个String最后被删除了,那么Redis就不会将这两条指令加入新的AOF中,由于已经被删除的数据,不需要恢复。再好比说,我们使用Redis维护了一个计数器cnt,我们使用了100INCR指令,让cnt自增到了100,而Redis重写AOF时,可以将这100incr修改为一条SET指令,直接将cnt设置为100,而不是保留100INCR

  经由了重写后,AOF的巨细将会大大减小,而且也去除了不必要的操作,优化了恢复数据的指令集。而AOF重写的历程与天生一个快照文件类似,如下:

  1. Redis执行fock(),建立一个子历程用来执行后续操作,而父历程继续处置发送到Redis的执行请求;
  2. 子历程重写旧AOF文件,将重写后的内容写入到一个临时文件;
  3. 若是这个历程中,有新的写指令到达,那么Redis会将这些写指令依旧追加到旧的AOF中,同时也会将这些指令加入到内存的一个缓冲区中。这样做的目的是,若是服务器发生异常,AOF重写失败,这些指令依然能够保留在旧AOF,不会丢失;
  4. 当子历程完成重写事情时,它给父历程发送一个信号,父历程在接收到信号之后,将内存缓存中的所有写指令追加到新 AOF 文件的末尾;
  5. 使用新AOF替换旧的AOF,这之后执行的所有写指令都将追加到新的AOF中;

2.8 AOF的错误处置

  AOF文件是有可能发生错误的,好比上面提过,若是当前Redis正在向AOF中追加一个写指令,然则此时服务器宕机,那么这个存入AOF中的这个写指令就是不完整的,也就是AOF泛起了错误。若是停机造成了 AOF 文件失足(corrupt), 那么 Redis 在重启时会拒绝载入这个 AOF 文件, 从而确保数据的一致性不会被损坏。

  那么,当AOF发生了错误,应该若何处置呢?我们可以使用如下下令:

redis-check-aof --fix:redis-check-aof用来检测AOF是否存在错误,若是指定了--fix参数,那么Redis在检测到AOF的错误后,会对AOF举行修复。

  redis-check-aof修复AOF的方式异常简朴:扫描AOF文件,寻找其中不正确或不完整的指令,当发现第一个失足的指令后,就将这个指令以及这之后的所有指令删除。为什么需要删除失足指令之后的所有指令呢?由于当一条指令失足,很有可能影响到后续的操作,导致后续操作的都是脏数据,而Redis无法检测哪些指令是受到影响的,以是为了保险起见,就将后续指令所有删除。不外不用忧郁,由于在大多数情况下,失足的都是AOF最末尾的指令。


2.9 AOF的优瑕玷

(1)优点:

  1. 使用 AOF 持久化会让 Redis 变得异常耐久,意思就是说,当发生异常导致需要重启服务器时,只会丢失很少的一部门数据,由于AOF持久化默认1s同步一次,也就是说,Redis最多只会丢失1s中所做的修改;
  2. Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 举行重写: 重写后的新 AOF 文件包罗了恢复当前数据集所需的最小下令聚集。
  3. AOF 文件有序地保留了对数据库执行的所有写入操作, 这些写入操作以 Redis 协议的花样保留, 因此 AOF 文件的内容异常容易被人读懂, 对文件举行剖析(parse)也很轻松。
  4. AOF 文件是一个只举行追加操作的日志文件(append only log), 因此对 AOF 文件的写入不需要举行 seek , 纵然日志由于某些缘故原由而包罗了未写入完整的下令(好比写入时磁盘已满,写入中途停机,等等), redis-check-aof 工具也可以轻易地修复这种问题。

(2)瑕玷:

  1. 对于相同的数据集来说,AOF 文件的体积通常要大于快照RDB文件的体积大,由于RDB只存储数据,而AOF中的写指令,既包罗指令,也包罗数据;
  2. 若是AOF体积太大,那么恢复数据将要破费较长的时间,由于需要重做指令;

2.10 选择快照照样AOF?

  说到这里,可能就有人要问了,在现实生产中,我们应该使用快照持久化照样AOF持久化呢?

1、若是希望自己的数据库有很高的安全性,则应该两者同时使用,AOF用作正确纪录,而快照用作数据备份,前面也说过,快照异常适合用来做数据备份,由于它只存储数据库中的数据,而且经由了压缩,而且它恢复Redis数据的速率一样平常要快于AOF

2、若是可以容忍一段时间内的数据丢失,则可以思量只使用快照持久化,减小服务器的开销;

  值得一提的是,若是我们同时开启了快照持久化和AOF持久化,Redis在重启后,会优先选择AOF来恢复数据,由于一样平常情况下,AOF能够加倍完整地恢复数据。


三、总结

  快照持久化和AOF持久化各有优劣,在现实生产环境中,我们一样平常是两者配合使用,快照持久化消耗较低,而且适合用于备份,然则会丢失一段时间的数据;AOF持久化加倍地耐久,可靠性更高,然则开销可能相对较高。以上就对Redis的持久化机制做了一个对照详细的先容,信赖看完只后,对Redis会有一个加倍深入的明白。


四、参考

  • 《Redis实战》
  • Redis官方文档——持久化
,

Sunbet

Sunbet www.114co.cn立足亚洲,展望国际,在即将到来的2019年,努力在技术、安全、服务上尽善尽美,致力提高业务品质,期望与业界精英共同开拓未来。

版权声明

本文仅代表作者观点,
不代表本站欧博网址的立场。
本文系作者授权发表,未经许可,不得转载。