美文网首页
一次 redis.cpu=100%+、QPS=14W+ 的故障解

一次 redis.cpu=100%+、QPS=14W+ 的故障解

作者: 猿来是八阿哥 | 来源:发表于2019-07-29 10:04 被阅读0次

故障描述

运维反馈说,redis 出现了 cpu100%+、QPS=14W+ 的情况,需要解决。


error.png

redis CPU=100%+ 的故障分析

问题是 cpu 打满了,所以猜测是计算量太多,同时,是 redis 和 mq 的消费者两端的进程都出现 cpu=100% 的情况,于是初步定为:

  1. mq 和 redis 计算量太多。
  2. mq 的消费者是多进程运行的,其中包含了 redis 的操作,必然是 mq 操作 redis 不当,才导致 mq 进程作为 redis 的 client,导致 redis 的 client 和 server 都 cpu=100%+。

定位 mq (redis client)中计算量大的程序片段

public function consumeToDo(AMQPMessage $message){
    list($result, $role) = $this->handleMessage($message);
    if($result){
        while(0 == Yii::$app->redis->setnx('xxx_lock', 1)){
            usleep(1000);
        }
        $counter = Yii::$app->redis->get('teacher_student_job_counter');
        list($teacher_job_counter, $student_job_counter) = explode('.', $counter);
        if($role == 'teacher'){
            Yii::$app->redis->set('teacher_student_job_counter', --$teacher_job_counter.'.'.$student_job_counter);
        }else{
            Yii::$app->redis->set('teacher_student_job_counter', $teacher_job_counter.'.'.--$student_job_counter);
        }
        Yii::$app->redis->del('xxx_lock');
    }
    return $result;
}

分析上述代码:为避免多进程操作 redis.teacher_student_job_counter 造成的结果异常,增加了“锁保护”,具体是:在操作前,争抢 xxx_lock 锁,在操作完 redis.teacher_student_job_counter 后在释放 xxx_lock 锁。但存在的问题有:

  1. setnx 的 sleep 时间太短,导致单位时间内操作 redis 的次数太多:1000次/秒。
  2. xxx_lock 锁没有过期时间,如果程序中途异常没有释放,有可能导致永远无法获取到 xxx_lock 锁。
    于是修复过后的代码为:
public function consumeToDo(AMQPMessage $message){
    list($result, $role) = $this->handleMessage($message);
    if($result){
        while(0 == Yii::$app->redis->setnx('xxx_lock', 1)){
            usleep(100000);
        }
        Yii::$app->redis->expire('xxx_lock', 10);
        $counter = Yii::$app->redis->get('class_student_job_counter');
        list($teacher_job_counter, $student_job_counter) = explode('.', $counter);
        if($role == 'teacher'){
            Yii::$app->redis->set('class_student_job_counter', --$teacher_job_counter.'.'.$student_job_counter);
        }else{
            Yii::$app->redis->set('class_student_job_counter', $teacher_job_counter.'.'.--$student_job_counter);
        }
        Yii::$app->redis->del('xxx_lock');
    }
    return $result;
}

redis QPS=10W+ 的故障分析

首先我让运维帮忙查看了下当前的 redis 连接:

connection.png
由图可以看出,redis 出现了很多 age>86400 的 setnx 连接,估计正是因为 xxx_lock 锁异常的问题导致的。于是将这些连接删除。
  1. 删除 age>86400 的 redis 连接
redis-cli -a password client list | awk '{split($5, agearr, "="); if(agearr[1]=="age" && int(agearr[2]) > 86400){split($2, addrarr, "="); print "redis-cli -a password client kill "addrarr[2];}}' | sh
  1. 删除正在执行 setnx 的 redis 连接
redis-cli -a password client list | grep cmd=setnx | awk '{split($2, addr, "="); print "redis-cli -a password client kill "addr[2];}' | sh

心得

在多进程使用 setnx 作为锁控制并发的时候,一定要控制抢锁的频率,避免 redis 的 client 和 server 的 cpu 过高。同时,应该为 setnx 锁设置合理的过期时间,避免在异常情况下造成 redis 连接时间太长、太多的问题(我们的场景是 mq 会根据队列长度,启动更多的进程来消费,于是连接越来越多)。

相关文章

  • 一次 redis.cpu=100%+、QPS=14W+ 的故障解

    故障描述 运维反馈说,redis 出现了 cpu100%+、QPS=14W+ 的情况,需要解决。 redis CP...

  • epoll

    传统的BIO BIO和QPS的关系: 1个线程的qps就是1. 100个线程的qps就是100 1000个线程的q...

  • 高并发优化方案

    高并发 QPS 每秒处理请求数 QPS 达到50一般服务器就能应付,不需要优化 QPS 达到100假设关系型数据库...

  • 记录一次压测经历

    背景:核心服务qps达到了500k+,核心数据大约占有400k+,还有100k左右的非核心数据请求,为做到服务解耦...

  • 2022-07-14 - 草稿

    1 海洋生物 100多个连号故障 2华兴家居 多线盘故障,水池水位不足 3新天地小区 多线盘故障 线路100多处...

  • 牛皮了!Redis 6.0 如何实现大幅度的性能提升

    导读: Redis可以轻松支撑100k+ QPS,离不开基于Reactor模型的I/O Multiplexing,...

  • redis 主从搭建

    什么是主从复制 为什么要使用主从复制 redis-server单点故障 单节点QPS有限 持久化,从处理持久化,避...

  • 微分享-高并发下的缓存实战

    场景 统计一个批量接口会有多少数据,这个接口的QPS在100万级别。有几种方案: 每次调用都串行计算一次; 每次调...

  • PV、TPS、QPS是怎么计算出来的

    TPS和QPS的区别术语说明:QPS = req/sec = 请求数/秒 【QPS计算PV和机器的方式】 QPS统...

  • redis主从复制与哨兵模式

    Redis主从复制 单机有什么问题单机故障、容量瓶颈、qps瓶颈。主机数据更新后根据策略和配置,自动同步到备机上。...

网友评论

      本文标题:一次 redis.cpu=100%+、QPS=14W+ 的故障解

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