redis-持久化

北慕城南 提交于 2019-12-10 03:19:04

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

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

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

redis-rdb持久化

rdb文件创建

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

  • save:
    • save命令在生成rdb文件期间会阻塞redis主进程,直到rdb文件创建完成之前redis主进程无法处理任何客户端请求
    • 由函数rdb.c/rdbSave函数执行、
    • www.wityx.com函数rdbSave本身就会阻塞进程
  • bgsave:
    • bgsave命令通过由主进程fork出一个子进程来执行生成rdb文件,生成rdb文件期间不会阻塞主进程
    • 由函数rdb.c/rdbSave函数执行
    • www.wityx.com
    • 问题: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文件来做数据库恢复
  • www.wityx.com

rdb自动间隔性保存

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

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

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

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

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

 redis-aof持久化

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

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

重写的实现:

  • 理论依据: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重写缓冲区
  • www.wityx.com
  • 最终aof文件重写完毕后,会将aof重写缓冲区文件同步写入新aof文件,保证了最终一致

aof重写步骤

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

rdb的实时性小于aof文件,所以rb不适合做redis的容灾方案,适合做冷备

aof文件适合做容灾方案,因为最理想情况下,aof方案只会丢失一个事件循环里的数

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!