如何排查并解决 Amazon DocumentDB 实例上的 CPU 利用率高的问题?
我想对 Amazon DocumentDB(兼容 MongoDB)实例上的 CPU 利用率高的问题进行故障排除。
简短描述
Amazon DocumentDB 实例的 CPU 利用率可帮助您了解当前分配的资源在持续工作负载下的性能。
由于以下原因,您可能会看到 CPU 利用率有所增加:
- 用户启动的繁重工作负载
- 查询效率低下
- 集群中的写入器负担过重,因为集群中的读取负载不平衡
- 读取器的硬件配置低于写入器,无法与高写入工作负载同步
- 内部任务,例如 Amazon DocumentDB 集群中的垃圾回收
- 数据库连接过多(空闲)
- 短暂的连接突增
解决方法
使用 Amazon CloudWatch 指标
使用 CloudWatch 收集和分析集群的运行指标。使用 CloudWatch 指标来识别较长时间段内的 CPU 及其比例指标模式。
在 CloudWatch 控制台中查看和监控以下指标:
- 使用 DatabaseConnections 和 DatabaseConnectionsMax 来识别在相关时间轴上打开的连接数量。
- 使用 WriteIOPs、ReadIOPs、ReadThroughput 和 WriteThroughput 来了解 Amazon DocumentDB 实例上的总体工作负载。
- 使用 DocumentsDeleted、DocumentsInserted、DocumentsReturned 和 DocumentsUpdated 来了解 Amazon DocumentDB 实例上的用户工作负载。
- 如果您使用 T3 或 T4 实例类,请查看 CPUCreditBalance 和 CPUSurplusCreditBalance 以检查计算限制。
使用性能详情指标
使用 Amazon DocumentDB 性能详情来识别导致数据库加载和等待状态的查询。在 Manage Metrics option(管理指标选项)下,使用平均活动会话数来查看负载和 CPU 分布(系统、用户或总计)。
当平均负载超过实例上的 vCPU 数量时,就会出现高负载。但是,如果平均负载小于数据库实例类的 vCPU 计数,则 CPU 节流可能不是应用程序延迟的原因。要确定 CPU 利用率增加的原因,请查看平均负载并分析与 I/O、锁定和锁存相关的等待状态。
使用本机数据库查询
使用本机查询分析工作负载并检查 CPU 利用率。要列出当前在 Amazon DocumentDB 实例上运行的所有操作,请使用 MongoDB Shell 运行以下查询:
db.adminCommand({currentOp: 1, $all: });
要列出所有被阻止或运行时间超过 10 秒的查询,请运行以下使用 currentOp 命令的查询:
db.adminCommand({ aggregate: 1, pipeline: [ {$currentOp: {}}, {$match: { $or: [ {secs_running: {$gt: 10}}, {WaitState: {$exists: true}} ] }}, {$project: { _id:0, opid: 1, secs_running: 1, WaitState: 1, blockedOn: 1, command: 1 }} ], cursor: {} });
要分析系统使用情况的结果,请在 CPU 利用率高的实例上运行以下查询:
db.adminCommand({ aggregate: 1, pipeline: [ { $currentOp: { allUsers: true, idleConnections: true } }, { $group: { _id: { desc: "$desc", ns: "$ns", WaitState: "$WaitState" }, count: { $sum: 1 } } } ], cursor: {} });
上述查询返回在每个命名空间中运行的所有查询的汇总。它还列出了所有内部系统任务以及每个命名空间的唯一等待状态数。
**注意:**内部任务下的 GARBAGE_COLLECTION 指标是 Amazon DocumentDB 集群中的多版本并发控制 (MVCC) 实施。这是一个后台清理器,用于移除失效的文档版本,并与数据库中的更新或删除次数相关。Amazon DocumentDB 会根据集合级别的内部阈值启动清理过程,这会导致读取或写入 IOPS 和 CPU 利用率。
检查查询的效率
检查写入查询的索引开销
过多或未使用的索引会减慢写入操作的速度。要提高性能,请检查索引使用情况统计信息,以便识别和移除不必要的索引。
查看查询的执行计划
当查询需要搜索集合中的每个文档时,速度会变慢。创建适当的索引以提高查询速度。
使用 explain 命令标识要在其上创建索引的字段。您还可以使用 profiler 日志来捕获长时间运行的查询及其操作的详细信息。
查看集合的统计信息
查看您使用的集合的以下统计信息:
- 查看性能详情中的 Top Queries(常用查询)部分,确定对负载贡献最大的集合。
- 查看集合的统计信息,了解 DocumentDB 执行插入、更新和删除操作的次数。您还可以查看进行索引扫描和完整集合扫描的次数。
- 拆分您的集合以减小需要处理的文档大小,尤其是在您有大量更新操作的情况下。
检查激进的日志记录设置
Amazon DocumentDB 会优先处理事件审计而非数据库流量。如果您不需要审计,则可以将其关闭。如果您需要审计,则将 audit_logs 参数设置为仅记录必要的事件。为增加负载做好计划,并根据需要切换到更大的实例类。
为避免 profiler 日志进行激进的日志记录,请确保为 profiler_threshold_ms 参数设置正确的值。检查您的应用程序工作负载,确定将查询归类为长时间运行所需的正确阈值。
为要导出到 CloudWatch 的日志启用 log exports(日志导出)选项。
使用最佳实践
将读取工作负载分流到读取器
如果您的 Amazon DocumentDB 集群中有多个数据库实例,请将读取工作负载分流到您的读取器实例。作为副本集连接时,请为连接指定 readPreference。如果您将读取首选项指定为 secondaryPreferred,则客户端会尝试将读取查询路由到您的副本。客户端尝试将写入查询路由到您的主数据库实例。
注意:读取器具有最终一致性。如果工作负载需要更强的写后读一致性,则使用动态读取首选项并在查询级别将其覆盖。例如,您可能会在连接级别默认为 secondaryPreferred,这样查询就会进入辅助查询。如果您的查询需要更强的写后读一致性,则可以覆盖默认设置并从主节点读取。
示例:
db.collection.find().readPref("primary")
向集群添加一个或多个读取器实例
如果您的 Amazon DocumentDB 集群只有单个数据库实例(仅限写入器),请向该集群添加一个或多个读取器数据库实例。然后使用 readPreference=secondaryPreferred 来有效地处理负载。
使用 Amazon DocumentDB Profiler 识别慢速查询
使用 Amazon DocumentDB Profiler 记录慢速查询。如果某个查询在慢速查询日志中反复出现,则可能需要额外的索引来提高性能。
检查执行计划中是否包含 COLLSCAN 阶段的长时间运行查询。COLLSCAN 阶段意味着查询必须读取集合中的每个文档才能提供对查询的响应。
有关更多信息,请参阅分析 Amazon DocumentDB(兼容 MongoDB)中运行缓慢的查询。
使用 CloudWatch 创建警报通知
创建 CloudWatch 警报,在 CPU 利用率指标超过特定阈值时通知您。
纵向扩展数据库实例的实例类
如果没有进一步的查询调整范围,请纵向扩展集群中实例的实例类以处理工作负载。
**注意:**如果纵向扩展实例类,则会增加成本。有关更多信息,请参阅 Amazon DocumentDB(兼容 MongoDB)定价。
