排查MongoDB CPU使用率高的问题

一、分析MongoDB数据库正在执行的请求

执行db.currentOp()命令,查看数据库当前正在执行的操作。命令的输出示例如下:

{
        "desc" : "conn632530",
        "threadId" : "140298196924160",
        "connectionId" : 632530,
        "client" : "11.192.159.236:57052",
        "active" : true,
        "opid" : 1008837885,
        "secs_running" : 0,
        "microsecs_running" : NumberLong(70),
        "op" : "update",
        "ns" : "mygame.players",
        "query" : {
            "uid" : NumberLong(31577677)
        },
        "numYields" : 0,
        "locks" : {
            "Global" : "w",
            "Database" : "w",
            "Collection" : "w"
        },
        ....

需要重点关注以下几个字段

字段返回值说明
client该请求是由哪个客户端发起的。
opid操作的唯一标识符。如果有需要,可以通过db.killOp(opid)直接终止该操作。
secs_running表示该操作已经执行的时间,单位为秒。如果该字段返回的值特别大,需要查看请求是否合理。
microsecs_running表示该操作已经执行的时间,单位为微秒。如果该字段返回的值特别大,需要查看请求是否合理。
ns该操作目标集合。
op表示操作的类型。通常是查询、插入、更新、删除中的一种。
locks锁相关的信息

备注:db.currentOp文档请参见此连接

通过db.currentOp()查看正在执行的操作,分析是否有不正常耗时的请求正在执行。例如您的业务平时CPU使用率不高,运维管理人员连到MongoDB数据库执行了一些需要全表扫描的操作导致CPU使用率非常高,业务响应缓慢,此时需要重点关注执行时间非常耗时的操作。

二、分析MongoDB数据库的慢请求

1、通过use <database>命令进入指定数据库。

use mongodbtest

2、执行如下命令,查看该数据下的慢请求日志。

db.system.profile.find().pretty()

3、分析慢请求日志,查找引起MongoDB CPU使用率升高的原因。
以下为某个慢请求日志示例,可查看到该请求进行了全表扫描,扫描了11000000个文档,没有通过索引进行查询。

{
        "op" : "query",
        "ns" : "123.testCollection",
        "command" : {
                "find" : "testCollection",
                "filter" : {
                        "name" : "zhangsan"
                },
                "$db" : "123"
        },
        "keysExamined" : 0,
        "docsExamined" : 11000000,
        "cursorExhausted" : true,
        "numYield" : 85977,
        "nreturned" : 0,
        "locks" : {
                "Global" : {
                        "acquireCount" : {
                                "r" : NumberLong(85978)
                        }
                },
                "Database" : {
                        "acquireCount" : {
                                "r" : NumberLong(85978)
                        }
                },
                "Collection" : {
                        "acquireCount" : {
                                "r" : NumberLong(85978)
                        }
                }
        },
        "responseLength" : 232,
        "protocol" : "op_command",
        "millis" : 19428,
        "planSummary" : "COLLSCAN",
        "execStats" : {
                "stage" : "COLLSCAN",
                "filter" : {
                        "name" : {
                                "$eq" : "zhangsan"
                        }
                },
                "nReturned" : 0,
                "executionTimeMillisEstimate" : 18233,
                "works" : 11000002,
                "advanced" : 0,
                "needTime" : 11000001,
                "needYield" : 0,
                "saveState" : 85977,
                "restoreState" : 85977,
                "isEOF" : 1,
                "invalidates" : 0,
                "direction" : "forward",
....in"
                }
        ],
        "user" : "root@admin"
}

通常在慢请求日志中,您需要重点关注以下几点。

  • 全表扫描(关键字: COLLSCAN、 docsExamined )
    ①全集合(表)扫描COLLSCAN 。
        当一个操作请求(如查询、更新、删除等)需要全表扫描时,将非常占用CPU资源。在查看慢请求日志时发现COLLSCAN关键字,很可能是这些查询占用了CPU资源。
    ②通过查看docsExamined的值,可以查看到一个查询扫描了多少文档。该值越大,请求所占用的CPU开销越大。
    备注: 如果这种请求比较频繁,建议对查询的字段建立索引的方式来优化。
  • 不合理的索引(关键字: IXSCAN、keysExamined )
        通过查看keysExamined字段,可以查看到一个使用了索引的查询,扫描了多少条索引。该值越大,CPU开销越大。
        如果索引建立的不太合理,或者是匹配的结果很多。这样即使使用索引,请求开销也不会优化很多,执行的速度也会很慢。
        如下所示,假设某个集合的数据,x字段取值的重复率很高(假设只有1、2),而y字段取值的重复率很低。
{ x: 1, y: 1 }
{ x: 1, y: 2 }
{ x: 1, y: 3 }
......
{ x: 1, y: 100000} 
{ x: 2, y: 1 }
{ x: 2, y: 2 }
{ x: 2, y: 3 }
......
{ x: 1, y: 100000}

要实现 {x: 1, y: 2} 这样的查询

db.createIndex( {x: 1} )         效果不好,因为x相同取值太多
db.createIndex( {x: 1, y: 1} )   效果不好,因为x相同取值太多
db.createIndex( {y: 1 } )        效果好,因为y相同取值很少
db.createIndex( {y: 1, x: 1 } )  效果好,因为y相同取值少

关于{y: 1} 与 {y: 1, x: 1} 的区别,可参见MongoDB索引原理复合索引官方文档

  • 大量数据排序(关键字: SORT、hasSortStage )
    当查询请求里包含排序的时候, system.profile 集合里的hasSortStage字段会为 true 。如果排序无法通过索引满足,MongoDB会在查询结果中进行排序。而排序这个动作将非常消耗CPU资源,这种情况需要对经常排序的字段建立索引的方式进行优化。
我们业务目前使用的是阿里云的云资源,关于云资源我配置了如下告警规则,请根据我的告警规则帮我设计一套基于规则的故障检测联合规则 ES-宕机【紧急】 ES-磁盘使用率 ES-内存使用率 ES-节点CPU使用率 ES-集群不健康 ES load kafka-消息堆积 kafka-消息生产量 kafka-消费量 kafka-磁盘使用率 mongodb-磁盘使用率 mongodb-内存使用率 mongodb-CPU使用率 mongodb-连接数 mongodb-实例重启 mysql-数据库宕机【紧急】 mysql-磁盘使用率 mysql-内存使用率【紧急】 mysql-数据库CPU使用率于70% mysql-IOPS使用率 mysql-连接池使用率 mysql-行锁时间长 mysql-慢查询过多 mysql-拒绝连接数 prometheus宕机 redis-内存使用率 redis-CPU使用率【紧急】 redis-实例发生重启 redis-连接率 redis-redis_averager_duration_high redis - 分片CPU使用率 redis BPS持续【紧急】 线程池活跃线程数 线程池队列占用率 node-宕机【紧急】 node-节点CPU使用率 node-节点inode使用率 node-节点内存使用率 node-节点磁盘使用率 节点池CPU request过 节点池CPU request于100%【紧急】 节点池CPU Limit于150% node-节点CPU iowait使用率 node-cat-节点内存使用率 核心EIP 流入带宽超150MB node 节点starcharge-prod 命名空间下pod超过11个 node 节点starcharge-prod 命名空间下L0应用超过6个 node-新加坡nginx节点CPU使用率 coredns 解析超时 Kafka Broker 异常
最新发布
04-01
<think>嗯,用户需要设计一套基于他们现有告警规则的故障检测联合规则。首先,我需要仔细看看他们配置的告警有哪些。他们用了阿里云,涉及ES、Kafka、MongoDB、MySQL、Redis、Node、线程池、Prometheus、EIP、CoreDNS等多个服务,每个服务都有不同的指标告警,有的标记为紧急。 首先,用户的需求是联合规则,也就是当多个告警同时触发时,能够更准确地判断故障根源。比如,ES宕机是紧急的,可能需要结合磁盘、内存、CPU的告警来判断是否因为资源不足导致的。或者,MySQL的宕机可能和磁盘使用率、IOPS有关联。所以,联合规则需要考虑不同服务之间的依赖关系和资源竞争情况。 接下来,需要分类处理这些告警。可能分成基础设施层、中间件层、数据库层、应用层等。比如,节点(node)的问题会影响上面运行的Pod和中间件,所以当节点宕机时,可能连带影响ES、Kafka等。这时候需要优先处理节点的问题,再检查其他服务。 然后,标记为紧急的告警需要优先处理。例如,ES-宕机、MySQL-数据库宕机、redis-CPU使用率紧急、节点池CPU request于100%紧急等。这些紧急告警可能需要立即响应,甚至自动触发某些恢复操作,比如扩容或重启实例。 另外,有些告警可能存在因果关系。比如,Kafka消息堆积可能是因为生产者消息量突然激增,或者消费者处理能力下降。这时候需要同时监控生产量、消费量和磁盘使用率,判断是源头问题还是处理端的问题。 还需要考虑资源瓶颈的连锁反应。例如,节点磁盘使用率可能导致Pod被驱逐,进而影响中间件如MySQL或Redis的运行,引发它们的告警。这时候需要从底层资源开始排查。 对于数据库类,比如MySQL,连接数、慢查询多、行锁时间长可能共同导致数据库响应变慢,甚至宕机。需要将这些关联指标结合起来,分析是否是同一问题导致的多指标异常。 此外,像CoreDNS解析超时可能会影响整个集群的服务发现,导致多个服务无法通信,这时候需要检查CoreDNS本身的资源使用情况,或者网络配置问题。 可能还需要考虑地域因素,比如用户提到的新加坡nginx节点CPU,可能需要单独处理,或者检查该区域的流量是否异常,比如EIP流入带宽是否超限。 最后,设计联合规则时,需要设定优先级,紧急告警优先,然后根据依赖关系层层递进。同时,可能需要设置抑制规则,避免重复告警,比如节点宕机导致的其他服务告警可以被抑制,直到节点恢复。 总结来说,联合规则需要从基础设施到应用层,按依赖关系分层,识别关键路径,关联相关指标,设定优先级和抑制策略,确保快速定位根本原因,避免告警风暴,提故障处理效率。</think>我将基于您列出的告警规则,设计一个分层级联的故障检测联合规则体系,分为三个层级:基础设施层、中间件层、应用层。以下是具体设计方案: 一、基础设施层优先检测(直接影响全局) ------------------------------------- $$ \text{紧急规则} = \text{节点宕机} \vee \text{EIP带宽超限} \vee \text{节点池CPU Request>100\%} $$ 1. **节点宕机联检**: - 当 `node-宕机【紧急】` 触发时 - 立即关联检查: $$ \text{节点存活率} = \frac{\text{存活节点数}}{\text{总节点数}} < 80\% $$ 若成立则触发集群级故障 2. **资源超限联检**: ```python if (节点池CPU Request >100%) or (EIP流入带宽 >150MB): 强制检查对应节点的CPU iowait、磁盘IOPS if 节点磁盘使用率 >85%: 标记为存储瓶颈型故障 ``` 二、中间件层联合检测(服务依赖关系) ----------------------------------- 1. **ES集群故障树**: $$ \text{ES故障} = \text{集群不健康} \wedge (\text{磁盘使用率}>85\% \vee \text{内存}>90\%) $$ - 当 `ES-磁盘使用率` + `ES load ` 同时触发时 - 自动检查 JVM 内存压力指标: $$ \text{内存压力指数} = \frac{\text{Young GC次数}}{\text{Old GC次数}} > 10:1 $$ 2. **Kafka消息堆积根因分析**: ``` WHEN (消息堆积量 > 1万条/秒) THEN IF 生产量突增 >300% → 标记为流量激增型故障 ELSE IF 消费量下降 >50% → 检查消费者线程池状态 ELSE IF 磁盘使用率 >90% → 标记为存储瓶颈 ``` 三、数据库层关键路径检测 ----------------------- 1. **MySQL紧急故障矩阵**: | 触发条件 | 关联指标 | 处置策略 | |-------------------------|----------------------------|-----------------------| | 数据库宕机 | 最后5分钟IOPS>基础值200% | 优先恢复主库 | | 行锁时间>30s + 慢查询>50 | 连接池使用率>90% | 触发SQL限流 | 2. **Redis级联检测模型**: $$ \text{Redis危机} = \left(\frac{\text{内存使用率}}{\text{连接率}} > 1.2\right) \wedge \left(\text{分片CPU} > 80\%\right) $$ - 当 `BPS持续` 触发时 - 自动关联检查: $$ \frac{\text{网络带宽使用量}}{\text{实例规格上限}} > 75\% $$ 四、应用层异常关联规则 --------------------- 1. **线程池雪崩预测**: $$ \text{风险系数} = \left(\frac{\text{活跃线程}}{\text{最大线程}}\right) \times \left(\frac{\text{队列占用率}}{100}\right) > 0.8 $$ - 当风险系数超标时: $$ \text{自动关联检查} = \text{慢查询数量} + \text{Redis响应时间} $$ 2. **Pod密度异常检测**: ``` IF (starcharge-prod Pod数量 >11) THEN 检查: 节点CPU使用率是否>80% 节点内存是否>85% IF 同时触发L0应用>6 → 标记为调度异常 ``` 五、全局抑制规则(避免告警风暴) ------------------------------- 1. 当 `节点宕机` 触发时: - 自动抑制该节点上所有中间件告警(ES/Kafka等) - 抑制时长为故障恢复时间+10分钟 2. 当 `CoreDNS解析超时` 触发时: $$ \text{抑制范围} = \text{所有依赖服务发现的应用告警} $$ 六、推荐配置的响应策略 --------------------- 1. **自动扩容规则**: ``` WHEN (CPU使用率 >85%持续5分钟) AND (节点池CPU Request <90%) AND (非突发流量) THEN 触发节点池自动扩容 ``` 2. **紧急熔断阈值**: | 服务 | 熔断条件 | 动作 | |------------|----------------------------------|--------------------------| | MySQL | 连接拒绝率>30%持续2分钟 | 切断非核心业务连接 | | Redis | 分片CPU>95%持续3分钟 | 启用只读模式 | 建议配合阿里云ARMS服务配置告警流水线,将以上规则划分为: - P0级(需立即人工介入):红色标记的【紧急】类告警 - P1级(自动处置+通知):黄色标记的资源类告警 - P2级(仅记录):蓝色标记的辅助指标告警
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值