Redis -- 06 -- Redis持久化方式之RDB

相关文章:


众所周知,Redis 的数据都是存放在内存当中的,如果没有配置持久化,当 Redis 重启后数据就会全部丢失,因此我们需要开启 Redis 的持久化功能,在这里我们先来了解下其中的一种方式:RDB


一、RDB

  • RDB (Redis DataBase)

    • 在指定时间间隔内,将内存中的数据保存到磁盘中,对应产生的数据文件默认为 dump.rdb

    • 当需要恢复数据时,可以直接将快照文件加载进内存中,来达到恢复数据的目的

  • 如何持久化

    • Redis 会单独创建 (fork) 一个子进程来进行持久化,会先将数据写入到一个临时 RDB 文件中,待持久化过程结束后,再用临时 RDB 文件替换原有的 RDB 文件

    • 在此过程中,子进程负责 IO 操作,主进程仍然负责处理客户端的请求,从而保证了 Redis 的高性能

  • 优势

    • 在进行大规模数据恢复时,RDB 要比 AOF 恢复速度快

    • 非常适合于文件备份,比如:我们可以在最近的24小时内,每小时备份一次 RDB 文件,或者在每个月的每一天,备份一次 RDB 文件,这样的话,当我们程序出现问题时,可以很容易地还原到不同的版本

    • 非常适合于灾难恢复,我们可以轻松地将 RDB 文件压缩后转移到其他存储介质上

    • 会单独创建一个子进程来进行持久化,子进程负责 IO 操作,主进程仍然负责处理客户端的请求,从而保证了 Redis 的高性能

  • 劣势

    • 由于 RDB 每隔一段时间才会进行持久化,因此在这段时间内,万一服务器出现问题宕机了,那么 Redis 就会丢失这一段时间内的所有数据,所以如果我们想要最大限度地避免数据丢失,那么 RDB 将不是一个很好的选择

    • 由于 RDB 是通过创建 (fork) 一个子进程来进行持久化工作,因此当数据集十分庞大时,创建 (fork) 子进程的操作将是非常耗时的,会使 Redis 服务出现卡顿现象


二、RDB 相关配置

  • save

    ################################ SNAPSHOTTING  ################################
    #
    # Save the DB on disk:
    #
    #   save <seconds> <changes>
    #
    #   Will save the DB if both the given number of seconds and the given
    #   number of write operations against the DB occurred.
    #
    #   In the example below the behaviour will be to save:
    #   after 900 sec (15 min) if at least 1 key changed
    #   after 300 sec (5 min) if at least 10 keys changed
    #   after 60 sec if at least 10000 keys changed
    #
    #   Note: you can disable saving completely by commenting out all "save" lines.
    #
    #   It is also possible to remove all the previously configured save
    #   points by adding a save directive with a single empty string argument
    #   like in the following example:
    #
    #   save ""
    
    save 900 1
    save 300 10
    save 60 10000
    
    • 配置说明

      指令作用
      save 900 1如果 900 秒内至少有 1 个 key 的值发生改变,则保存
      save 300 10如果 300 秒内至少有 10 个 key 的值发生改变,则保存
      save 60 10000如果 60 秒内至少有 10000 个 key 的值发生改变,则保存
    • 如果想禁用 RDB 配置,只需要在上面配置最后一行加上 save "" 即可

  • stop-writes-on-bgsave-error

    # By default Redis will stop accepting writes if RDB snapshots are enabled
    # (at least one save point) and the latest background save failed.
    # This will make the user aware (in a hard way) that data is not persisting
    # on disk properly, otherwise chances are that no one will notice and some
    # disaster will happen.
    #
    # If the background saving process will start working again Redis will
    # automatically allow writes again.
    #
    # However if you have setup your proper monitoring of the Redis server
    # and persistence, you may want to disable this feature so that Redis will
    # continue to work as usual even if there are problems with disk,
    # permissions, and so forth.
    stop-writes-on-bgsave-error yes
    
    • 当 stop-writes-on-bgsave-error 设置为 yes 时,表示当备份进程出错时,主进程就会停止接收写入操作,从而保证了持久化数据的一致性

    • 当然,如果我们的业务有完善的监控系统,则可以禁止此项配置,没有的话,还是建议开启

  • rdbcompression

    # Compress string objects using LZF when dump .rdb databases?
    # For default that's set to 'yes' as it's almost always a win.
    # If you want to save some CPU in the saving child set it to 'no' but
    # the dataset will likely be bigger if you have compressible values or keys.
    rdbcompression yes
    
    • 当 rdbcompression 设置为 yes 时,表示在备份的时候,需要将 RDB 文件进行压缩后再进行保存

    • 这里建议将其设置为 no,因为 Redis 本身属于 CPU 密集型服务器,再开启压缩,会带来更多的 CPU 消耗,相比硬盘成本,CPU 性价比更高


三、save 与 bgsave 的区别

  • 在 Redis 中,save、bgsave 都可用于指定 RDB 文件的同步策略,两者区别如下

    • save

      • save 指令会阻塞 Redis 的主进程,直到 RDB 文件被创建完为止 (一般很少使用)
    • bgsave

      • bgsave 指令会创建 (fork) 一个子进程来创建 RDB 文件,不会阻塞 Redis 的主进程

      • 当子进程完成了 RDB 文件的创建后,会发送信号给主进程,与此同时主进程会通过轮询来接收子进程的信号

  • 我们可以通过 lastsave 指令来查看同步操作是否成功

    • lastsave

      • 记录了上一次成功执行 save 或 bgsave 指令的时间
  • 因此我们可以通过定时任务调用 Redis 的 bgsave 指令去备份 RDB 文件,并按照时间戳存储不同的 RDB 文件,作为 Redis 某段时间的全量数据备份


四、bgsave 原理

在这里插入图片描述

  • 在执行了 bgsave 指令后,Redis 会先去检查当前主进程是否存在正在执行的 AOF / RDB 子进程,如果存在,则返回错误,这是为了防止子进程之间的相互竞争 (即在执行 bgsave 期间,客户端再次发送 save 或 bgsave 指令时,会被 Redis 拒绝执行);如果不存在,则会触发持久化,此时会调用 Redis 源码中的 rdbSaveBackground 方法,执行 fork 系统调用,创建一个子进程来完成数据备份操作

  • fork 指令是用来创建子进程的,在 Linux 下 fork 系统调用实现了Copy-on-Write (写时复制)

    • 在传统方式下,父进程在创建子进程时,会把所有资源都复制给子进程,这种方式实现简单,但效率低下,可能存在复制的资源对于子进程毫无作用的情况

    • 在 Linux 下,为了降低创建子进程的成本,改进了 fork 的实现方式:当父进程创建子进程时,内核为子进程创建了虚拟空间,父子两个进程使用相同的物理空间,只有当父子进程发生更改时,才会为子进程分配单独的物理空间,这种改进方式即为写时复制

  • 什么是 Copy-on-Write (COW,写时复制)?

    • 如果有多个调用者同时请求相同资源 (如内存或磁盘上存储的数据),它们会获取相同的指针来指向相同的资源,直到某个调用者试图修改资源的内容时,系统才会真正复制一份专用副本给该调用者,而其他调用者所见到的资源仍保持不变

    • 此做法的优点在于:如果调用者没有修改该资源,就不会有副本被创建,因此多个调用者只是进行读取操作时,可以共享同一份资源

    • 在 COW 的处理过程中,需要维持一个为读请求使用的指针,并在新数据写入完成后更新这个指针,以提升读写并发能力,因此 COW 也间接地提供了数据更新过程中的原子性,在保证数据完成性的同时,还保证了一定的读写效率


五、自动触发 RDB 持久化的方式

  • 根据配置文件中的 save m n 指令定时触发 (用的 bgsave)

  • 主从复制时,主节点会自动触发

  • 执行 Debug Reload 时会自动触发

  • 执行 Shutdown 且没有开启 AOF 持久化时会自动触发


六、参考资料

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值