• redis-持久化


    redis是一个键值对的内存数据库服务器,它将数据库状态存储在内存之中,但是如果一旦服务器出现问题意外crash或者重启那么内存中的数据库状态将全部丢失,为了解决这个问题,redis提供了持久化方案,将内存中数据库状态同步到磁盘保障数据

    redis提供了两种持久化方案:rdb,aof

    • rdb方式:将数据库状态(数据库中键值对)保存为一个经过压缩的二进制文件
    • aof方式:将数据库写命令保存为一个固定格式的文件

    redis-rdb持久化

    rdb文件创建

    redis通过两个命令来用于生成rdb文件:

    • save:
      • save命令在生成rdb文件期间会阻塞redis主进程,直到rdb文件创建完成之前redis主进程无法处理任何客户端请求
      • 由函数rdb.c/rdbSave函数执行、
      • 函数rdbSave本身就会阻塞进程
    • bgsave:
      • bgsave命令通过由主进程fork出一个子进程来执行生成rdb文件,生成rdb文件期间不会阻塞主进程
      • 由函数rdb.c/rdbSave函数执行
      • 问题:bgsave命令执行期间服务器如何处理save,bgsave,bgrewriteaof三个命令
        • bgsave命令执行期间Redis服务器拒绝执行save命令,防止主进程和子进程同时执行rdbSave函数导致资源竞争
        • bgsave命令执行期间Redis服务器拒绝执行bgsave命令,防止两个子进程同时执行rdbSave函数导致资源竞争
        • bgsave和bgrewriteaof命令吧態同时执行
          • bgsave执行期间bgrewriteaof命令会被延后,直到bgsave执行完成才可以执行bgrewriteaof
          • bgrewriteaof执行期间,bgsave命令会被丢弃

    rdb文件载入

    rdb文件载入实在服务器启动的时候就会自动执行,所以redis并没有专门的用关于rdb文件载入的命令,只要redis服务器检测到rdb文件就会自动载入rdb文件

    rdb文件载入期间,主进程处于阻塞状态,直到载入完成才可以执行客户端命令

    问题:如果rdb方式和aof方式同时开启,redis服务器如何使用持久化方式恢复的

    • 如果aof方式开启,由于aof方式的实时性更高,所以redis会优先使用aof文件来恢复数据库
    • 只有aof方式处于关闭状态,redis服务器才会使用rdb文件来做数据库恢复

    rdb自动间隔性保存

    由于bgsave在执行期间不会阻塞主进程,所以redis允许通过配置服务器配置save属性,让服务器在满足条件的情况下自动还行bgsave

    配置放在redis.conf文件中,格式为:save  <seconds> <changes>

    • 当满足在seconds秒内,redis数据库执行过changes次修改,那么就会触发自动bgsave
    • save属性可以设置多个,在设置多个的情况下,满足任意一个就会自动执行
    • redis默认配置:

    如何触发自动间隔性保存?

    • redis的时间事件执行周期性的函数serverCron默认每100ms执行一次扫描。会检查设置的save属性是否满足
    • 如果条件满足那么就会执行bgsave,否则继续周期扫描检测

     redis-aof持久化

    aof的持久化功能实现可以分为:命令追加,文件写入,文件同步三个步骤

    • 命令追加:当aof功能处于打开状态,服务器在执行完写命令后,会将这个写命令追加到aof_buf内存缓冲区中
    • 文件写入和文件同步:
      • redis主进程本身就是一个事件循环event-loop
      • 处理文件事件执行写命令,并追加到aof_buf

      • 处理时间事件执行周期任务

      • 结束事件循环前-调用flushAppendOnlyFile函数考虑将aof_buf内容写入和保存早aof文件中

        •  flushAppendOnlyFile的函数行为由服务器配置:appendfsync属性决定,属性值不同则产生不同的行为

          • appendfsync=always:总是将aof_buf缓冲区内容同步写入到aof文件中

            • 安全性最高,只会丢失一个事件循环内的数据
            • 效率最差,大量的I/O操作
          • appendfsync=everysec:每秒周期的将aof_buf缓冲区同步的写入到aof文件中

            • 安全性适中,丢失一秒内的写数据
            • 效率适中
          • appendfsync=no:不执行将aof_buf缓冲区内容同步到aof文件的操作

            • 安全性最差,丢失自上次之后所有数据
            • 效率最高

    aof文件的载入和数据还原

    aof文件中包含了重建数据库的所有写口令,所以服务器只需要读入命令并且重新执行一遍aof文件中命令,就可以还原数据库

    • 1:创建一个无网络连接的伪客户端:因为redis的命令执行能在客户端执行。所以利用伪客户端来执行aof文件中命令
    • 2:从aof文件中分析并读取一条写命令
    • 3:使用伪客户端执行读取到的写命令
    • 4:循环执行2,3直到完全执行完所有aof文件中命令

    aof重写

    aof文件是通过记录写命令来实现持久化,但是存在一个问题:对同一个key在给定时间内会发生多次写操作,所以aof文件存在越变越大的问题,而体积过大aof文件对于redis服务器的压力会变大,所以需要解决这一弊端;最好的情况是无论执行多久,对于相同的key在aof文件中只存在一条有效的能够保障当前数据库状态的写命令,所以redis提供了重写功能

    重写的实现:

    • 触发条件:
      • 手动触发:执行bgrewriteaof命令
      • 自动触发:配置属性
        • auto-aof-rewrite-min-size :aof文件最小重写大小
        • auto-aof-rewrite-percentage:当前aof文件大小与最后一次重写后大小比率,100表示aof是上次重写时两倍才重写
    • 理论依据:aof重写时通过读取当前服务器数据库状态来实现的
      • 通过aof文件中的key从redis数据库中获取key的当前状态并将当前状态装换为写命令来实现
    • 实际操作:
      • redis提供了aof_write函数来实现redis-aof重写
      • aof_write函数在执行期间会阻塞主进程

    aof后台重写

    由于aof_write在执行期间会阻塞主进程,而aof重写只是一种辅助手段,所以redis不希望重写阻塞主进程,所以提供aof后台重写功能,aof重写由主进程fork出的子进程来执行aof重写,主进程则继续接受和执行客户端命令

    问题:aof后台重写期间主进程依旧执行写命令,导致数据状态最终不一致

    • redis在aof后台重写期间会开启aof重写缓冲区
    • 主进程在aof后台重写期间每执行一条写命令,都会将写命令同时发送到aof缓冲区和aof重写缓冲区
    • 最终aof文件重写完毕后,会将aof重写缓冲区文件同步写入新aof文件,保证了最终一致

    aof重写步骤

    • 开始后台aof重写,主进程fork子进程开始执行bgrewriteaof命令
    • 主进程将重写期间的写命令同时发送到aof缓冲求,aof重写缓冲区
    • 子进程完成aof重写工作,向主进程发送一个信号
    • 主进程接收到信号调用信号处理函数
    • 将aof重写缓冲器数据写入新的aof文件
    • 重命名新的aof文件并原子覆盖旧aof文件
    • 重写完成

    如何合理使用持久化

    rdb文件紧凑单一但是实时性弱,aof耐久实时性好但是体积会大,基于二者在性能,安全性,实时一致性上的特点,rdb更加适合做冷备份,非常便于数据库备份;aof适合做热备份,适合做容灾。但是小孩子才做选择,在线上生产环境当然是选择两种持久化方式同时开启使用,利用rdb来保存数据库数据副本,利用aof记录实时的命令

    redis4.0混合持久化

    4.0的新特性,将rdb与aof持久化方式二合一结合了两者的优点,可以快速加载同时避免丢失过多数据,缺点就是文件可读性差

    新特性中aof文件会由两部分组成,一半是rdb格式,一半是aof格式

     混合持久化过程

    • 发生时间点:aof-rewrite被触发
    • 如何开启:aof-use-rdb-preamble yes (redis5.0默认开启)
    • aof-rewrite流程:
      • fork子进程遍历old-aof文件读取数据库状态写入new-aof文件
      • 在写new-aof期间新的写命令会记录在重写缓冲区中
      • 当写new-aof完成,子进程通知主进程,主进程将重写缓冲区数据写入new-aof文件
      • 重命名并原子替换old-aof
    • aof-rdb混合持久化:
      • fork子进程会以rdb的格式将数据库状态写入new-aof文件
      • 在写入new-aof期间新的写命令会记录在重写缓冲区中
      • 子进程以rdb格式同步数据库状态ok,通知主进程
      • 主进程会将重写缓冲区中增量命令以aof格式写入new-aof文件
      • 重命名并原子替换old-aof
    • aof-rdb混合持久化加载:
      • 加载方式依旧遵循优先aof文件
      • 当开启aof并开启混合持久化时优先加载混合aof文件
        • 混合aof文件以顺序加载
        • 先rdb后aof
      • 否则,由aof先aof,否则rdb

    总结:

    • rdb优点:
      • 结构紧凑(二进制压缩文件)体积小,适合容灾恢复
      • 恢复大数据集时比aof快 (rdb记录的是数据库键值对信息)
      • 可以最大化redis性能(bgsave是fork子进程执行)
    • rdb缺点:
      • 快照数据,数据完整度不高,适合冷备不适合热备
      • 数据量大时,子进程耗费cpu越多,耗时越久
      • 文件二进制格式,可读性差
    • aof优点:
      • 数据完整度高(appendfsync=always丢失一个事件循环的数据)
      • 兼容性高(命令追加)
    • aof缺点:
      • 数据体积大,就算aof-rewrite(命令追加导致)
      • aof加载速度比rdb慢(一条条由伪客户端执行命令)
  • 相关阅读:
    ipfs cluster 模式部署使用(docker-compose 环境运行)
    lerna import && add 使用&&常见问题解决
    memsql kafka集成
    memsql 6.7集群安装
    过程、性能基线、性能模型与目标之间的关系
    oracle extract函数
    ORACLE的VARCHAR2是字节还是字符
    infor系统日常问题解决笔记
    Oracle获取当前年、月、日的方法
    Windows下Redis中RedisQFork位置调整
  • 原文地址:https://www.cnblogs.com/cavaliersyb/p/12011255.html
Copyright © 2020-2023  润新知