zoukankan      html  css  js  c++  java
  • 【Redis】Redis两种持久化方式AOF和RDB

    Redis的持久化

      redis所有的数据都是保存在内存中,当redis进程挂了或者机器出现宕机等异常情况,如果不讲数据保存在硬盘中,那么数据将会丢失。redis就提供了持久化的功能,就是可以将所有的数据修改也会异步更新在磁盘上。

    Redis的持久化方式   

      Redis提供了两种持久化的方式:

        1. RDB:这是一种快照的方式,它将Redis某时间点的数据都进行快照存储。比如Mysql Dump也是这种方式。

        2. AOF:写日志的方式,记录每次对服务器写的操作, 当服务器重启的时候会重新执行这些命令来恢复原始的数据。例如Mysql binlog,Hbase HLog。

    RDB(Redis DataBase)

      一. RDB介绍

            在 Redis 运行时, RDB 将当前内存中的数据库生成一个Snapshot快照保存到磁盘文件中, 在 Redis 重启动时, RDB 可以通过载入 RDB 文件来还原数据库的状态。

      

         二. RDB的触发方式:

        RDB 有三种触发方式,其实就是生成RDB文件的方式。 

        1. save命令:这个是同步方式,会阻塞当前其他的命令执行,直到save命令执行完毕。

        2. bgsave命令:这个是一个异步命令,会单独在后台去执行,不会阻塞其他命令。它其实是新创建(fork)了一个子进程,这个进程就是负责生成RDB文件的工作。

        3. 自动方式:就是在某些条件下会自动去生成,这个是在Redis配置文件中去设置。

          

           这里说一下上面配置时间策略具体的意思。

             1. 900秒内有一个key变化

             2. 300秒内10个key变化

             3. 60秒内有10000个key发生变化。

        三. RDB的文件生成策略

        如果存在老的RDB文件,那么会生成一个临时文件,然后新生成的文件就会替换老的RDB文件。

        四. Save和Bgsave命令的区别

    命令 save bgsave
    IO类型 同步 异步
    是否阻塞 是(阻塞发生在fork时候,不过fork是非常快的)
    时间复杂度 O(n) O(n)
    优点 不会消耗额外内存 不会阻塞客户端命令执行
    缺点 会阻塞客户端命令执行 需要fork 消耗内存

      五. RDB的持久化配置选项

    # 时间策略
    save 900 1
    save 300 10
    save 60 10000
    
    # RDB文件名称
    dbfilename dump.rdb
    
    # 文件保存路径
    dir /home/work/app/redis/data/
    
    # 如果持久化出错,主进程是否停止写入
    stop-writes-on-bgsave-error yes
    
    # 是否压缩
    rdbcompression yes
    
    # 导入时是否检查
    rdbchecksum yes

     六. RDB最佳配置  

      这里RDB最佳配置也是相对而言,具体也可以根据线上环境和具体业务来调整。这里只是一般通常配置

    # RDB文件名称加上端口号进行文件的区别,现在机器多核,会运行多个Redis实例可以充分利用多核优势,这样产生多个RDB文件进行区分 
    dbfilename dump-${port}.rdb
    # 文件保存路径
      dir /空间大的路径
    # 如果持久化出错,主进程是否停止写入,这里选择开启,如果bgsave发生错误就不能正常的写入,说明redis就可能会出现问题了,这时候应该停止写入
    stop-writes-on-bgsave-error yes
    # 是否压缩,采用压缩,这样文件会比较小,而且Redis主从复制之间会有拷贝
    rdbcompression yes
    

     七. 触发机制-不容忽略方式

       1. 全量复制:有时候没有执行save,bgsave命令或者配置文件设置RDB自动生成方式时候也会生成RDB文件,那是因为可能主从之间会有全量复制导致生成的,主节点会自动生成RDB文件。

       2. debug reload:进行debug级别的重启,不会将Redis内存进行清空的重启,这个时候也会触发RDB文件的生成。

       3. shutdown save:这个也会导致RDB文件的生成。

    AOF

      一. AOF介绍

        Redis的另一种持久化方式就是AOF(Append Only File),与RDB持久化通过保存数据库中的键值对来记录数据库状态不同,AOF是通过保存Redis所执行的写命令来记录数据库状态的。在了解AOF之前先看看RDB所存在的问题。

       二. RDB所存在的问题

        1. 耗时,耗性能,每次保存 RDB 的时候Redis 都要 fork() 出一个子进程,并由子进程来进行实际的持久化工作。 在数据集比较庞大时fork() 可能会非常耗时,比如写的数据量很大,内存页设置的比较大,会产生很大的内存消耗,造成服务器在某某毫秒内停止处理客户端, 如果数据集非常巨大,并且 CPU 时间非常紧张的话,那么这种停止时间甚至会更长。同时RDB也是一个IO的过程,RDB文件很大拷贝速度就会很慢。

        

        2. 不可控,容易丢失数据,服务器在发生故障时候会丢失数据。

         下面是一个时间线流程操作说明

          

          T3和T4时间段所操作的命令都会丢失。因为无法知道什么时候会宕机及其他异常情况。如果使用save和bgsave做定时备份也是无法保障数据不会丢失。

          如果避免RDB所出现的问题,这里就需要AOF。

           AOF运行工作图

           

         客户端每执行一条命令都会被记录在AOF文件中。当Redis服务器宕机后,Redis可以从AOF文件中恢复数据。

         

         

       三. AOF三种策略

         Redis提供了三种决定AOF写入的频率。

         Redis在执行写入AOF日志文件的时候不是直接去写入文件中,而是先记录在硬盘的缓冲区,缓冲区会根据一些刷新策略来决定什么时候刷新到磁盘中,这样会提高写入的效率。

         1. always: 每次写入一条数据就立即将这个数据对应的写日志fsync到磁盘上去,虽然可以确保Redis里的数据一条都不丢,但是性能非常差,吞吐量很低。

          

               2. everysec:每秒将缓冲中的数据fsync到磁盘,这个比较最常用的,生产环境一般都这么配置,而且性能很高。但是缺点就是不像always那样保证每个命令都会记录,Redis服务器出现故障有可能会丢失一秒钟的数据。

          

         3. no: 仅仅redis负责将数据写入缓冲区,什么时候刷新到磁盘中是根据操作系统自己决定。这种一般不会使用。

         

         三种策略对比

    命令 always everysec no
    优点 不丢失数据 每秒一次fsync 不用管
    缺点 IO开销大,一般SATA盘每秒只有几百TPS 可能会丢一秒的数据 不可控

         在保证数据不丢失,硬盘开销方面作了权衡,使用everysec策略会更加合适。

       四. AOF 重写实现原理

         AOF策略保证Redis命令写入到AOF文件中,不过随着命令逐步的写入,时间的推移,并发量写入量逐步的变大,AOF文件的体积也会逐渐的变大。这时候使用AOF进行恢复数据会变的很慢。当AOF文件无限制的变大,无论是对于文件的管理,写入命令的速度都会有一定的影响。所以Redis提供了一个AOF重写的机制来解决这些问题。

        

         根据上图分析原生AOF那一列最上面写入三条命令,都是对同一个key进行操作的,最后一次将前面两次写入的值更新了,实际上只有最后一次修改对我们是有用的。中间的incr自增命令也是一样的。下面三次rpush也是可以优化的,可以统一成一个命令。同时对于一些过期的数据,当时写入到AOF文件中,但是某个时间点已经过期了,这个key内部会执行一个删除命令操作并同步到AOF文件中,这个在AOF重写中是没有用的。

         所以可以得出AOF重写的作用

           将过期的,没有用的,重复的命令,以及一些可以优化的命令都进行一个精简,来缩小AOF文件的体积,减少对磁盘的占用量。同时文件体积缩小也可以加速Redis恢复的速度。

       五. AOF 重写的两种方式

        1. 手动触发(Bgrewriteaof命令):这个命令有点类似于RDB中的bgsave,Bgrewriteaof 命令会fork一个子进程用于异步执行一个 AOF(AppendOnly File) 文件重写操作,重写会创建一个当前 AOF 文件的体积优化版本。即使 Bgrewriteaof 执行失败,也不会有任何数据丢失,因为旧的 AOF 文件在 Bgrewriteaof 成功之前不会被修改。

           注意:从 Redis 2.4 开始, AOF 重写由 Redis 自行触发, BGREWRITEAOF 仅仅用于手动触发重写操作。

          

                   Bgrewriteaof命令工作图

        1. 自动触发:

            自动触发与AOF重写配置几个参数有关。

             1)auto-aof-rewrite-min-size:AOF文件重写需要的最小的大小。就是说当AOF文件至少多大体积的时候在开始进行重写,默认64M。

             2)auto-aof-rewrite-percentage:AOF文件增长率。当进行过了一次重写,下一次进行重写的时候看这个AOF文件的增长率,默认100。

             3)aof_current_size:当前AOF文件的大小(单位:字节)。

           4)aof_base_size:上一次操作或者重写后的AOF文件大小(单位:字节)。

           触发条件 :

              aof_current_size > auto-aof-rewrite-min-size 并且 (aof_current_size  - aof_base_size) / aof_base_size >= auto-aof-rewrite-percentage。其中,aof_current_size是当前AOF文件大小,aof_base_size 是上一次重写后AOF文件的大小,这两部分的信息可从info Persistence处获取。

       

         AOF重写流程图

          

       六. AOF配置项

    # 打开AOF持久化机制,默认是no
    appendonly yes
    # AOF文件名
    appendfilename appendonly-${port}.aof
    # AOF同步策略
    appendfsync everysec

    # 文件保存路径
      dir /空间大的路径

    #在AOF重写时候是否做正常的AOF的append操作,如果该参数设置为no,是最安全的方式,不会丢失数据,但是要忍受阻塞的问题。如果设置为yes呢?这就相当于将appendfsync设置为no,这说明并没有执行磁盘操作,只是写入了缓冲区,因此这样并不会造# 成阻塞(因为没有竞争磁盘),但是如果这个时候redis挂掉,就会丢失数据。丢失多少数据呢?在linux的操作系统的默认设置下,最多会丢失30s的数据。
    no-appendfsync-on-rewrite yes

      

          七. AOF优缺点

         1. 优点

          1)AOF机制可以带来更高的数据安全性。

          2)由于该机制对日志文件的写入操作采用的是append模式,因此在写入过程中即使出现宕机现象,也不会破坏日志文件中已经存在的内容

          3)AOF包含一个格式清晰、易于理解的日志文件用于记录所有的修改操作。

         2. 缺点

          1)对于相同数量的数据集而言,AOF文件通常要大于RDB文件。RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快

          2)AOF对系统开销有一定的影响。AOF常用的持久化策略是everysec,在这种策略下,fsync同步文件操作由专门线程每秒调用一次。当系统磁盘较忙时,会造成Redis主线程阻塞,所以在Redis的负载较高情况下,RDB 比 AOF 具好更好的性能保证。

    RDB和AOF的选择

      RDB和AOF对比

    命令 RDB AOF
    启动优先级(Redis同时开启了RDB和AOF,Redis先加载哪个)
    体积 小(RDB使用二进制模式存储,并做了压缩,体积比较小)
    恢复速度 快(体积比较小所以恢复速度快)
    数据安全性 丢数据(RDB快照所以容易丢失数据) 根据策略来决定
    命令操作的轻重(比如是否耗时,耗资源) 重(备份Redis时间点全部数据)

        RDB和AOF的选择

         如果可以忍受一小段时间内数据的丢失,毫无疑问使用 RDB 是最好的,定时生成 RDB 快照(snapshot)非常便于进行数据库备份, 并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快,而且使用 RDB 还可以避免 AOF 一些隐藏的 bug;否则就使用 AOF 重写。但是一般情况下建议不要单独使用某一种持久化机制,而是应该两种一起用,在这种情况下,当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。Redis后期官方可能都有将两种持久化方式整合为一种持久化模型。

    参考来源及其他资料

      https://www.runoob.com/redis/server-bgrewriteaof.html

        https://www.iteye.com/blog/carlosfu-2254570

  • 相关阅读:
    设计模式:单一职责原则
    多线程的创建
    Android开发基础(java)14
    面向对象编程的思想(6)
    面向对象编程的思想(5)未完成
    面向对象编程的思想(4)
    面向对象编程的思想(3)
    面向对象编程的思想(2)
    面向对象编程的思想(1)
    GDB 命令详细解释
  • 原文地址:https://www.cnblogs.com/songgj/p/9408784.html
Copyright © 2011-2022 走看看