redis持久化

作者: 打伞的Fish | 来源:发表于2018-06-24 11:14 被阅读31次

    通读文章你会知道如下:

    • redis持久化的方式有哪些?
    • RDB和AOF两者的区别
    • RDB持久化的流程是怎么进行的?
    • AOF持久化方式如何开启?文件的同步策略有哪些,各自代表什么含义?
    • AOF的重写机制执行过程是怎么样的?
    • 持久化方式对系统的内存,硬盘和CPU各自会产生什么问题,有什么优化的方式?

    1.RDB持久化方式

    • 含义:RDB持久化是把当前进程数据生成快照保存到硬盘的过程
      bgsave命令: Redis进程执行fork操作创建子进程, RDB持久化过程由子进程负责, 完成后自动结束。 阻塞只发生在fork阶段, 一般时间很短
    • 自动触发RDB持久化机制执行情况
      1. 使用save相关配置, 如“save m n”。 表示m秒内数据集存在n次修改 时, 自动触发bgsave。
      2. 如果从节点执行全量复制操作, 主节点自动执行bgsave生成RDB文件并发送给从节点
      3. 执行debug reload命令重新加载Redis时, 也会自动触发save操作。
      4. 默认情况下执行shutdown命令时, 如果没有开启AOF持久化功能则 自动执行bgsave
    • bgsave命令运行流程
    bigsave命令执行流程
    1. 执行bgsave命令, Redis父进程判断当前是否存在正在执行的子进程, 如RDB/AOF子进程, 如果存在bgsave命令直接返回。
    2. 父进程执行fork操作创建子进程, fork操作过程中父进程会阻塞, 通过info stats命令查看latest_fork_usec选项, 可以获取最近一个fork操作的耗时, 单位为微秒。
    3. 父进程fork完成后, bgsave命令返回“Background saving started”信息并不再阻塞父进程, 可以继续响应其他命令。
    4. 子进程创建RDB文件, 根据父进程内存生成临时快照文件, 完成后对原有文件进行原子替换。 执行lastsave命令可以获取最后一次生成RDB的时间, 对应info统计的rdb_last_save_time选项。
    5. 进程发送信号给父进程表示完成, 父进程更新统计信息, 具体见info Persistence下的rdb_*相关选项。
    • 设置存储的路径以及文件名称

    可以通过执行config set dir{newDir}和config setdbfilename{newFileName}运行期动态执行, 当下次运行时RDB文件会保存到新目录,AOF相同设置

    • RDB方式的优缺点
    1. 优点:非常适用于备份, 全量复制等场景。 比如每6小时执行bgsave备份,并把RDB文件拷贝到远程机器或者文件系统中(如hdfs) , 用于灾难恢复。·Redis加载RDB恢复数据远远快于AOF的方式
    2. 缺点:RDB方式数据没办法做到实时持久化/秒级持久化。 因为bgsave每次运行都要执行fork操作创建子进程, 属于重量级操作, 频繁执行成本过高

    2. AOF持久化方式

    开启AOF功能需要设置配置: appendonly yes, 默认不开启。 AOF文件名通过appendfilename配置设置, 默认文件名是appendonly.aof

    • 含义:以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中的命令达到恢复数据的目的。 AOF的主要作用是解决了数据持久化的实时性。
    • 运行流程
    运行流程
    1. 所有的写入命令会追加到aof_buf(缓冲区) 中。
    2. AOF缓冲区根据对应的策略向硬盘做同步操作。
    3. 随着AOF文件越来越大, 需要定期对AOF文件进行重写, 达到压缩的目的。
    4. 当Redis服务器重启时, 可以加载AOF文件进行数据恢复。
    • 文件的同步

    AOF将buf数据同步到文件的策略由参数appendfsync控制


    同步文件的策略

    系统调用write和fsync说明:

    1. write操作会触发延迟写(delayed write) 机制。 Linux在内核提供页缓冲区用来提高硬盘IO性能。 write操作在写入系统缓冲区后直接返回。 同步硬盘操作依赖于系统调度机制, 例如: 缓冲区页空间写满或达到特定时间周期。 同步文件之前, 如果此时系统故障宕机, 缓冲区内数据将丢失。
    2. fsync针对单个文件操作(比如AOF文件) , 做强制硬盘同步, fsync将阻塞直到写入硬盘完成后返回, 保证了数据持久化
      默认配置everysec
    • 重写机制
    1. 含义:随着命令不断写入AOF, 文件会越来越大, 为了解决这个问题, Redis引入AOF重写机制压缩文件体积。 AOF文件重写是把Redis进程内的数据转化为写命令同步到新AOF文件的过程。
      重写使用的是进程内的数据生成,这样减少无效命令,同时可以多条命令合并一个。
    2. 触发情况
      手动触发: 直接调用bgrewriteaof命令。
      自动触发: 根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数确定自动触发时机。
      auto-aof-rewrite-min-size: 表示运行AOF重写时文件最小体积, 默认为64MB。
      auto-aof-rewrite-percentage: 代表当前AOF文件空间(aof_current_size) 和上一次重写后AOF文件空间(aof_base_size) 的比值。
      自动触发时机=aof_current_size>auto-aof-rewrite-minsize&&(aof_current_size-aof_base_size) /aof_base_size>=auto-aof-rewritepercentage
      其中aof_current_size和aof_base_size可以在info Persistence统计信息中查看(但是实践中没找到这个参数呢?,额,额, 额, )
    • 重写执行流程
    1. 当前进程如果正在执行 AOF重写,请求则不执行,如果正在执行bgsave操作,重写命令延迟到此操作完成之后再执行
    2. 父进程执行fork创建子进程,开销等同于bgsave过程
    3. 主进程fork操作完成后, 继续响应其他命令。 所有修改命令依然写入AOF缓冲区并根据appendfsync策略同步到硬盘, 保证原有AOF机制正确性
    4. 由于fork操作运用写时复制技术, 子进程只能共享fork操作时的内存数据。 由于父进程依然响应命令, Redis使用“AOF重写缓冲区”保存这部分新数据, 防止新AOF文件生成期间丢失这部分数据
    5. 子进程根据内存快照, 按照命令合并规则写入到新的AOF文件。 每次批量写入硬盘数据量由配置aof-rewrite-incremental-fsync控制, 默认为32MB, 防止单次刷盘数据过多造成硬盘阻塞
    6. 新AOF文件写入完成后, 子进程发送信号给父进程, 父进程更新统计信息, 具体见info persistence下的aof_*相关统计。
    7. 父进程把AOF重写缓冲区的数据写入到新的AOF文件。
    8. 使用新AOF文件替换老文件, 完成AOF重写


      重写执行过程
    • AOF重启加载

    优先加载AOF


    AOF与RDB加载情况

    3.持久化的一些问题

    • fork操作的耗时

    fork创建的子进程不需要拷贝父进程的物理内存空间, 但是会复制父进程的空间内存页表,因此fork
    操作耗时跟进程总内存量息息相关

    1. 优先使用物理机或者高效支持fork操作的虚拟化技术, 避免使用Xen。
    2. 控制Redis实例最大可用内存, fork耗时跟内存量成正比, 线上建议每个Redis实例内存控制在10GB以内
    3. 降低fork操作的频率, 如适度放宽AOF自动触发时机, 避免不必要的全量复制等
    • 子进程开销监控
    1. CPU:子进程负责把进程内的数据分批写入文件,属于CPU密集型操作,如果做绑定单核CPU操作会和父进程进行资源的竞争,跟其他CPU密集型服务一起会产生CPU过度竞争,,部署多个实例保证同一个时刻只有一个子进程在进行重写工作。
    2. 内存:父子进程会共享相同的物理内存页, 当父进程处理写请求时会把要修改的页创建副本, 而子进程在fork操作过程中共享整个父进程内存快照,如果重写过程中存在内存修改操作, 父进程负责创建所修改内存页的副本,所以部署多个实例,则保证同一个时刻只有一个子进程在工作,同时避免在大量写入的时候进行重写操作,这样会导致父进程维护大量的页副本。
    • 硬盘开销
    1. 不要和其他高硬盘负载的服务部署在一起。 如: 存储服务、 消息队列服务等。
    • AOF追加阻塞
    1. 主线程负责写入AOF缓冲区。
    2. AOF线程负责每秒执行一次同步磁盘操作, 并记录最近一次同步时间。
    3. 主线程负责对比上次AOF同步时间:
      ·如果距上次同步成功时间在2秒内, 主线程直接返回。
      ·如果距上次同步成功时间超过2秒, 主线程将会阻塞, 直到同步操作完成。
      问题:
      如果系统fsync缓慢, 将会导致Redis主线程阻塞影响效率
      每当发生AOF追加阻塞事件发生时, 在info Persistence统计中,aof_delayed_fsync指标会累加, 查看这个指标方便定位AOF阻塞问题。
      AOF同步最多允许2秒的延迟, 当延迟发生时说明硬盘存在高负载问题, 可以通过监控工具如iotop, 定位消耗硬盘IO资源的进程


      持久化指标参数

    相关文章

      网友评论

        本文标题:redis持久化

        本文链接:https://www.haomeiwen.com/subject/isacyftx.html