zoukankan      html  css  js  c++  java
  • Redis持久化——问题定位与优化(三)

    核心知识点:

    1.fork操作

      a.在RDB或AOF重写时,会执行fork操作创建子进程,fork操作是一个重量级操作。

      b.改善fork操作耗时的手段:避免使用Xen、配置Redis实例最大使用内存、合理配置Liunx内存使用技术、降低fork操作的频率。

    2.子进程开销监控与优化

      1).CPU

      2).内存

      3).硬盘

    3.AOF追加阻塞

    Redis持久化功能一直是影响Redis性能的高发地,下面我们结合常见的持久化功能问题进行分析定位和优化。

    一、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失败。

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

    二、子进程开销监控和优化

    子进程负责AOF或者RDB文件的重写,它的运行过程主要涉及CPU、内存、硬盘三部分的消耗。

    1.CPU

    (1)CPU开销分析

    子进程负责把进程内的数据分批写入文件,这个过程属于CPU密集操作,通常子进程对单核CPU利用率接近90%。

    (2)CPU消耗。

    Redis是CPU密集型操作,不要做绑定单核CPU的操作。由于子进程非常消耗CPU,会和父进程产生单核资源竞争。

    不要和其他CPU密集型服务部署在一起,造成CPU过度竞争。

    如果部署多个Redis实例,尽量保证同一时刻只有一个子进程执行重写工作。

    2.内存

    (1)内存消耗分析

    子进程通过fork操作产生,占用内存大小等同于父进程,理论上需要两倍的内存来完成持久化的操作,但是Linux有写时复制机制。

    父进程会共享相同的物理内存页,当父进程处理写请求时会把要修改的页创建副本,而子进程在fork操作过程中共享整个父进程内存快照。

    (2)内存消耗监控

    如果重写过程中存在内存页操作,父进程负责创建所修改内存页的副本,从日志中可以看出这部分的内存消耗。

    父进程维护页副本消耗同RDB重写过程类似,不同之处在于AOF重写需要AOF重写缓冲区。

    提示:编写shell脚本根据Redis日志可快速定位子进程重写期间内存过度消耗的情况。

    (3)内存消耗优化

    • 同CPU优化一样,如果部署多个Redis实例,尽量保证同一时刻只有一个子进程在工作。
    • 避免大量写入时做子进程重写操作,这样将导致父进程维护大量页副本,造成内存消耗。

    在Linux kernel在2.6.38内核增加了Transparent Huge pages(THP),支持huge page(2MB)的页分配,默认开启。

    当开启时可以降低fork创建子进程的速度,但执行fork之后,如果开启HTP,复制页单位会从原来4KB变为2MB,会大幅增加重写期间父进程的内存消耗。

    3.硬盘

    (1)硬盘开销分析

    子进程主要职责是把AOF或者RDB文件写入硬盘持久化,势必会造成硬盘写入压力,

    根据Redis重写AOF/RDB的数据量,结合系统工具如sar、iotop等,可分析出重写期间硬盘负载情况。

    (2)硬盘开销优化

    • 不要和其它高硬盘负载的服务部署在一起。如:存储服务、消息队列服务。
    • AOF重写时会消耗大量硬盘IO,可以开启配置no-appendfsync-on-rewrite,默认关闭。表示在AOF重写期间不做fsync操作。
    • 当开启AOF功能的Redis用于高流量写入场景时,如果使用普通机械磁盘,写入吞吐一般在100MB/s左右,这是瓶颈主要在AOF同步硬盘上。
    • 对于单机配置多个Redis实例的情况,可以配置不同实例分盘存储AOF文件,分摊硬盘写入压力。

    三、AOF追加阻塞

    当开启持久化时,常用的同步硬盘的策略是everysec,用于平衡性能和数据安全性。

    对于这种方式,Redis使用另一条线程每秒执行fsync同步硬盘。当系统硬盘资源繁忙时,会造成Redis主线程阻塞。

    1.阻塞流程分析:

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

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

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

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

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

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

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

    2.AOF阻塞问题定位

    (1)发生AOF阻塞问题,Redis会在日志中记录其行为。

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

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

  • 相关阅读:
    C#:将子Form加入父Form中
    C#:简单线程样例
    C#:实现接口中定义的事件
    easyui设置界面的高度自适应
    JQuery
    vim常用命令(iOS)
    Linux的IO性能监控工具iostat详解
    php多线程抓取信息测试例子
    使用Gitosis搭建Git服务器
    CentOS 6.4 搭建git 服务器
  • 原文地址:https://www.cnblogs.com/yangmingxianshen/p/8407972.html
Copyright © 2011-2022 走看看