Redis持久化原理之RDB和AOF

Redis 有两种持久化方案,RDB (Redis DataBase)和 AOF (Append Only File)。

RDB

      RDB 是 Redis 默认的持久化方案。在指定的时间间隔内(周期性),执行指定次数的写操作,则会将内存中的数据写入到磁盘中。即在指定目录下生成一个dump.rdb文件。Redis 重启会通过加载dump.rdb文件恢复数据。触发RDB持久化过程分为手动触发和自动触发。

相关的命令使用

      save命令: 阻塞当前Redis服务器, 直到RDB过程完成为止, 对于内存比较大的实例会造成长时间阻塞, 线上环境不建议使用

      bgsave命令: Redis进程执行fork操作创建子进程, RDB持久化过程由子进程负责, 完成后自动结束。

压缩

      Redis默认采用LZF算法对生成的RDB文件做压缩处理, 压缩后的文件远远小于内存大小, 默认开启, 可以通过参数config set rdbcompression {yes|no}动态修改。虽然压缩RDB会消耗CPU,但可大幅降低文件的体积,因此线上建议开启。

优缺点     

   优点:
  • RDB是一个紧凑压缩的二进制文件, 代表Redis在 某个时间点上的数据快照。 非常适用于备份, 全量复制等场景。
  • Redis加载RDB恢复数据远远快于AOF的方式。
   缺点:
  • RDB方式数据没办法做到实时持久化/秒级持久化。 因为bgsave每次运行都要执行fork操作创建子进程, 属于重量级操作, 频繁执行成本过高。
  • RDB文件使用特定二进制格式保存, Redis版本演进过程中有多个格式的RDB版本, 存在老版本Redis服务无法兼容新版RDB格式的问题。

AOF

    AOF(append only file) 持久化: 以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中的命令达到恢复数据的目的。 AOF的主要作用是解决了数据持久化的实时性, 目前已经是Redis持久化的主流方式。内容为文本协议格式
    开启AOF功能需要设置配置:appendonly yes,默认不开启。AOF的默认文件名是appendonly.aof。

优缺点

    优点:AOF是一秒一去通过一个后台的线程fsync操作,那最多丢这一秒的数据。AOF是以追加的方式写数据,自然就少了很多磁盘寻址的开销。
    缺点:一样的数据AOF文件比RDB文件要大。

AOF的具体流程

  1. 所有的写入命令会追加到aof_buf(缓冲区) 中。
  2. AOF缓冲区根据对应的策略向硬盘做同步操作。
  3. 随着AOF文件越来越大, 需要定期对AOF文件进行重写, 达到压缩的目的。
  4. 当Redis服务器重启时, 可以加载AOF文件进行数据恢复。

    AOF缓冲区同步文件策略

  1. always---命令写入aof_buf后调用系统fsync操作同步到AOF文件,fsync完成后线程使用。效率较低。不建议配置
  2. everysec---命令写入aof_buf后调用系统write操作,write完成后线程返回。fsync同步文件操作由专门线程每秒调用一次。默认配置-兼顾性能和安全性,理论上只有在系统突然宕机的情况下丢失1秒的数据。
  3. no---命令写入aof_buf后调用系统write操作,不对AOF文件做fsync同步,同步硬盘操作由操作系统负责,通常同步周期最常30秒。数据安全性无法保证

    AOF的write操作和fsync操作

  • write操作会触发延迟写(delayed write) 机制。 Linux在内核提供页缓冲区用来提高硬盘IO性能。 write操作在写入系统缓冲区后直接返回。 同步硬盘操作依赖于系统调度机制, 例如: 缓冲区页空间写满或达到特定时间周期。同步文件之前, 如果此时系统故障宕机, 缓冲区内数据将丢失。
  • fsync针对单个文件操作(比如AOF文件) , 做强制硬盘同步, fsync将阻塞直到写入硬盘完成后返回, 保证了数据持久化。

    AOF重写机制

       AOF文件重写是把Redis进程内的数据转化为写命令同步到新AOF文件的过程。重写后的AOF文件越来越小的原因如下:
  1. 进程内已经超时的数据不再写入文件。
  2. 旧的AOF文件含有无效命令。
  3. 多条写命令可以合并为一个。

Redis重写AOF或RDB文件时出现的问题:

1.fork操作

     当Redis做RDB或AOF重写时, 一个必不可少的操作就是执行fork操作创建子进程, 对于大多数操作系统来说fork是个重量级操作。 虽然fork创建的子进程不需要拷贝父进程的物理内存空间, 但是会复制父进程的空间内存页表。 例如对于10GB的Redis进程, 需要复制大约20MB的内存页表, 因此fork操作耗时跟进程总内存量息息相关, 如果使用虚拟化技术, 特别是Xen虚拟机, fork操作会更耗时。

     fork耗时问题定位: 对于高流量的Redis实例OPS可达5万以上, 如果fork操作耗时在秒级别将拖慢Redis几万条命令执行, 对线上应用延迟影响非常明显。 正常情况下fork耗时应该是每GB消耗20毫秒左右。 可以在info stats统计中查latest_fork_usec指标获取最近一次fork操作耗时, 单位微秒。

    如何改善fork操作的耗时:

   1) 优先使用物理机或者高效支持fork操作的虚拟化技术, 避免使用Xen。

   2) 控制Redis实例最大可用内存, fork耗时跟内存量成正比, 线上建议每个Redis实例内存控制在10GB以内。

   3) 合理配置Linux内存分配策略, 避免物理内存不足导致fork失败, 具体细节见12.1节“Linux配置优化”。

   4) 降低fork操作的频率, 如适度放宽AOF自动触发时机, 避免不必要的全量复制等。

2.AOF追加阻塞

     同步硬盘的策略是everysec, 用于平衡性能和数据安全性。 对于这种方式, Redis使用另一条线程每秒执行fsync同步硬盘。 当系统硬盘资源繁忙时, 会造成Redis主线程阻塞。

     阻塞流程分析:

    1) 主线程负责写入AOF缓冲区。

    2) AOF线程负责每秒执行一次同步磁盘操作, 并记录最近一次同步时间。

    3) 主线程负责对比上次AOF同步时间:

  • 如果距上次同步成功时间在2秒内, 主线程直接返回。

  • 如果距上次同步成功时间超过2秒, 主线程将会阻塞, 直到同步操作完成。

    通过对AOF阻塞流程可以发现两个问题:

    1) everysec配置最多可能丢失2秒数据, 不是1秒。

    2) 如果系统fsync缓慢, 将会导致Redis主线程阻塞影响效率。

    AOF阻塞问题定位:

    1) 发生AOF阻塞时, Redis输出如下日志, 用于记录AOF fsync阻塞导致拖慢Redis服务的行为:

    Asynchronous AOF fsync is taking too long (disk is busy). Writing the AOF buffer without waiting for fsync to complete, this may slow down Redis

    2) 每当发生AOF追加阻塞事件发生时, 在info Persistence统计中,aof_delayed_fsync指标会累加, 查看这个指标方便定位AOF阻塞问题。

    3) AOF同步最多允许2秒的延迟, 当延迟发生时说明硬盘存在高负载问题(优化系统硬盘负载即可), 可以通过监控工具如iotop, 定位消耗硬盘IO资源的进程。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值