企业级Redis开发运维从入门到实践 (19)— 开发运维常见问题(fork操作、子进程开销和优化、AOF追加阻塞、单机多实例部署持久化优化)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zx711166/article/details/82970605

fork

fork操作
  1. 同步操作:执行 bgsave、bgrewriteaof都是首先执行一个fork操作,fork只是做一个内存页的拷贝,大部分情况下速度都是很快的;但是本次的 fork 操作卡在某个地方将会阻塞Redis的主线程
  2. 与内存量息息相关:实例内存越大,fork 耗时越长(与机器类型有关)。
  3. info:latest_fork_usec(上次执行 fork 的微秒数),这个数值比较大将会阻塞Redis
改善fork
  1. 优先使用物理机或者高效支持 fork 操作的虚拟化技术,避免使用 Xen。
  2. 控制Redis实例最大可用内存(maxmemory),fork耗时跟内存量成正比,线上建议 每个Redis实例内存控制在10GB以内。
  3. 合理配置 Linux 内存分配策略:vm.overcommint_memory=1(默认值是0,当发现没有足够内存做内存分配时就不去分配,对于 fork 来说会造成 fork 的阻塞)。
  4. 降低fork操作的频率,如适度放宽 AOF 自动触发时机,避免不必要的全量复制等。

子进程

子进程开销和优化
CPU
  • 开销:RDB 和 AOF 文件生成(即文件的重写),例如执行basave、bgrewriteaof 的时候,最终将内存的数据写入硬盘,不仅存在内存、硬盘的开销;也存在CPU的开销,通常这个子进程的CPU开销会在90%以上(因为写入是一个非常集中的过程),所以是CPU密集型
  • 优化:
    1、不做CPU绑定(不要Redis的进程绑定在一个CPU上,否则子进程主进程将会集中消耗CPU,会对主进程造成很大的影响);
    2、不要和CPU密集型的应用部署在一起(减少CPU资源的竞争)。
内存
  • 开销:
    子进程通过fork操作产生,占用内存大小等同于父进程,理论上需要两倍的内存来完成持久化操作,但Linux有写时复制机制 (copy-on-write)。父子进程会共享相同的物理内存页,当父进程处理写请 求时会把要修改的页创建副本,而子进程在fork操作过程中共享整个父进程内存快照。
  • 优化:
    1、不允许单机多部署的时候产生大量的重写;
    2、在主进程写入量比较少的时候做 AOF 重写或 bgsave;
    3、建议设置“sudo echo never>/sys/kernel/mm/transparent_hugepage/enabled”关闭THP(Linux kernel在2.6.38内核增加了Transparent Huge Pages(THP),支持 huge page(2MB)的页分配,默认开启)。
硬盘
  1. 开销:AOF 和 RDB 文件写入,可以结合 iostat、iotop工具进行分析。
  2. 优化:
    1、不要和高硬盘负载服务部署在一起:存储服务、消息队列等;
    2、AOF重写时会消耗大量硬盘IO,可以开启配置no-appendfsync-onrewrite,默认关闭。表示在AOF重写期间不做fsync操作;
    3、根据写入量决定磁盘类型:例如SSD;
    4、单机多实例持久,可以配置不同实例分盘存储 AOF文件,分摊硬盘写入压力。

AOF追加阻塞

使用everysec做刷盘策略的流程

阻塞流程分析:

  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.
  1. 每当发生 AOF 追加阻塞事件发生时,在 info Persistence 统计中,aof_delayed_fsync 指标会累加,查看这个指标方便定位 AOF 阻塞问题。
redis> info persistence
.....
.....
aof_delayed_fsync: 100
.....
.....
  1. AOF 同步最多允许2秒的延迟,当延迟发生时说明硬盘存在高负载问题,可以通过监控工具如iotop,定位消耗硬盘IO资源的进程。

多实例部署

当多个实例开启AOF重写后,彼此之间会产 生对CPU和IO的竞争。

对于单机多Redis部署,如果同一时刻运行多个子进程,对当前系统影响将非常明显,因此需要采用一种措施,把子进程工作进行隔离。

Redis在info Persistence中为我们提供了监控子进程运行状况的度量指标。

属性名 属性值
rdb_basave_in_progress bgsave 子进程是否正常运行
rdb_current_bgsave_time_sec 当前运行 bgsave 的时间,-1 表示未运行
aof_enabled 是否开启 AOF 功能
aof_rewrite_in_progress AOF 重写子进程是否正在运行
aof_rewrite_scheduled 在 bgsave 结束后是否运行 AOF 重写
aof_current_rewrite_time_sec 当前运行 AOF 重写时间,-1 表示未运行
aof_current_size AOF 文件当前字节数
aof_base_size AOF 上次重写 rewrite 的字节数

基于以上指标,可以通过外部程序轮询控制 AOF 重写操作的执行,流程说明:

  1. 外部程序定时轮询监控机器(machine)上所有Redis实例。
  2. 对于开启 AOF 的实例,查看(aof_current_size — aof_base_size)/aof_base_size 确认增长率。
  3. 当增长率超过特定阈值(如100%),执行 bgrewriteaof 命令收到触发当前实例的 AOF 重写。
  4. 运行期间循环检查 aof_rewrite_in_progress 和 aof_current_rewrite_time_sec 指标,知道 AOF 重写结束。
  5. 确认实例 AOF 重写完成后,在检查其他实例并重复 2~4 步操作。从而保证机器内每个Redis实例 AOF 重写串行化执行。

在这里插入图片描述

展开阅读全文

没有更多推荐了,返回首页