Redis持久化——问题定位与优化

Posted 明王不动心

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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资源的进程。

 

以上是关于Redis持久化——问题定位与优化的主要内容,如果未能解决你的问题,请参考以下文章

Redis配置与优化

Redis配置与优化

2021最新京东Java面试题目,从理论到实践!

涨知识:flume消费kafka数据从最新位置开始

mysql查看数据库文件位置,含爱奇艺,小米,腾讯,阿里

吃透这份阿里P8纯手打Java面经,java冒泡排序算法