谭新宇的博客

谭新宇的博客

马上订阅 谭新宇的博客 RSS 更新: https://tanxinyu.work/atom.xml

2023 IoTDB 用户大会分享:如何用 IoTDB 监控工具进行深度系统调优

2023年12月7日 18:03

背景

2023 年 12 月 3 日,IoTDB 一年一度的 用户大会 成功举办。

在本次大会中,我有幸作为讲师之一做了《优其效:如何用 IoTDB 监控工具进行深度系统调优》的分享,系统介绍了 IoTDB 这一年来在可观测性方面的进展,并展示了它如何显著提升我们的性能调优和问题排查效率。

本博客将通过文字和图片的方式展示我的分享内容。

我们在可观测性方面做的工作后续也会有更多的博客输出出来,敬请期待!

内容

大家好,我是来自天谋科技的谭新宇,接下来我为大家分享的主题是”如何用 IoTDB 监控工具进行深度系统调优”。

本次分享分为 5 个方面,首先我们将介绍数据库系统的用户服务和架构演进挑战,这些挑战的本质都是如何去提升效率;接着我们会对 IoTDB 可观测性的发展进行概览,主要包括 Logging,Metrics 和 Tracing 三个方面;然后我们会介绍一下 IoTDB 的监控模块,其构建主要参考了火焰图作者著作《性能之巅》的思路,即从负载视角和资源视角两个维度对系统进行观测;最后我们会概述一下 IoTDB 的 4 个监控面板并着重做一些性能调优和问题排查的典型案例分享。

首先先来分析一下数据库系统的用户服务和架构演进有着怎样的挑战。

对于用户服务,主要存在以下三个挑战:

第一是如何快速找到业务场景的瓶颈点?系统的性能存在木板效应,会受限于系统最慢的模块,比如某节点的 CPU 和磁盘还没有打满,但网卡已经被打满了,此时增加写入负载也不会获得任何性能上的提升。

第二是如何对业务场景进行针对性调优?不同硬件环境和业务负载的排列组合会使得很多默认参数并不是当下最优的值,针对这个问题,一种理想流派是像 ottertune 一样使用机器学习的方式去找到最优的参数组合,另一种更为实际的流派则是能够对系统进行白盒调优。

第三是如何形成可扩展的调优体系?对于性能调优这个工作,其实非常容易形成马太效应,即越会调优的人越容易被分配更多性能调优的工作,虽然他会越来越能调优,但这也容易形成单点瓶颈,导致调优工作横向扩展不起来,这样其实是不利于整个产研团队和实施团队的共同成长的。因此需要针对调优这项工作形成可复制的调优方法论,大家共享互补调优的知识,一起成长。

对于架构演进,也主要存在以下三个挑战:

第一是如何确定典型业务场景?性能优化需要结合场景谈论才有意义,而一个系统往往也会有很多用户场景,这就需要从中抽象出来通用普适的典型场景并总结他们的典型特征。比如硬件环境到底是 4 核 8G 还是 64 核 128G ,业务需求到底是追求低延迟还是高吞吐等等。

第二是如何进一步演进典型业务场景下的性能?任何系统在特定业务场景下都存在进一步性能演进的可能,我们需要在寻找瓶颈的过程中区分出来哪些是工程问题(比如 GC 参数调优,代码写的冗余),哪些是学术问题(比如针对 IoTDB 特定的时序场景,有些数据库原理的 trade-off 发生了变化,这个时候就可以结合场景做一些更针对的设计,IoTDB 近几年在 Fast 和 ICDE 等顶会上发表的论文都是沿着这个思路去设计的),区分出这两个问题之后就可以利用不同的思路去并行协作优化性能了。

第三是如何确保性能优化的 ROI 最大?对于一个系统怎么优化,收集一圈能够得到一大堆思路,到底哪些效果会好,哪些效果会差?我们需要能够精确评估一个优化的正向作用和负面影响,并能够量化排列优先级,这样才可能将有限的资源持续投入到 ROI 最大的性能优化上,坚持做最正确的选择。

分析完了挑战,其实我们也都清楚了可观测性对于解决这些挑战的重要性。那么接下来我们介绍一下 IoTDB 的可观测性发展概览。

随着分布式架构成为主流,可观测性这一名词逐渐被大家频繁提及。学术界一般会将可观测性分为三个更具体的方向进行研究,分别是 Logging,Metrics 和 Tracing。

Logging 的职责是记录离散事件,从而使得事后可以通过这些记录来分析程序的行为。

Metrics 的职责是将不同类型的消息分别进行统计聚合处理,从而能够对系统进行持续的监控和预警。

Tracing 的职责是记录完整的调用轨迹,这就包含了服务间的网络传输信息与各个服务内部的调用堆栈信息。

IoTDB 自诞生时就使用了 Logback 框架来管理日志,随着版本的不断迭代,目前已经将不同级别和模块的日志拆分成了不同的文件便于检索。

虽然这些日志很重要,但它所有的信息都是离散的。如果要对某一类的信息进行一些汇总聚合统计,比如统计一段时间的平均刷盘点数,就需要首先 cat 文件,接着再 grep 过滤出同一类型的日志,然后还要写脚本来计算次数,平均值之类的,这就非常繁琐。

很自然的这就需要引入 Metrics 了。

IoTDB 在 0.12 版本就开始设计开发 Metrics,但从 1.0 版本之后才开始投入大量精力打磨 Metrics,到了 1.3 版本 Metrics 已经基本打磨的差不多了。

我们用了 Micrometer 和 DropWizard 的算法库来作为监控指标的类型支撑,具体的存储可以导出到 Prometheus 或者 IoTDB 中,可视化目前主要是在用 Grafana 工具。

右边贴了一张我们监控面板的图,还是非常漂亮的,后面会进一步介绍。

有了 Metric 之后,我们可以统计同一类请求的聚合信息,例如平均值,P99 值等等。这其实已经能够解决 90% 以上的问题,但对于剩下 10% 的问题,比如海量小查询和一个大查询并发执行时,大查询的执行耗时会被吞并,从而无法体现在 Metrics 中。此时我们就需要具备单独观测一条请求完整调用链路耗时的能力。

为了满足这种需求,今年我们也启动了对 Tracing 工作的研究,我们用 OpenTelemetry,ElasticSearch 和 Grafana 搭建了 Tracing 系统。

比如右图对于 show region 请求的调用链路,我们可以在 Grafana 中展示这个请求跨进程通信时不同进程内部调用栈的详细耗时信息,这对于慢查询等场景的性能排查效率会有显著提升。

总体而言,IoTDB 的可观测性能力在今年发生了质变。我们有信心也非常欢迎我们的用户朋友前来体验。

接下来我会着重介绍一下 IoTDB 的监控模块:

对于监控模块而言,它的灵魂就是他拥有哪些监控指标。

这里我们参照火焰图作者著作《性能之巅》的思路。从负载分析和资源分析这两个相反的角度去互补推进监控指标体系的建设。

对于自顶向下的负载视角:

我们对客户端写入 IoTDB 的流程进行了拆解。对于每个 IoTDB 的连接,当它将请求交给到 IoTDB 执行时,该连接被视为忙碌状态;当它在客户端攒批等待或者向服务端传输时,该连接被视为闲置状态。通过这种区分,我们能够对瓶颈是否在 IoTDB 内部有一个评估。比如每次连接繁忙都是 10ms,之后却要闲置 5 分钟,那基本瓶颈就不在 IoTDB 端了。

如果发现连接繁忙的时间要更大,要如何进一步去寻找瓶颈呢。我们将 IoTDB 的写入请求延迟进行了拆解,将写入流程分成了若干阶段,并对一般情况下更为耗时的阶段进行了更细粒度的拆分,从而能够确保发现瓶颈出现在哪个模块。比如调度执行阶段一直存在远程转发,那就需要去排查客户端的分区缓存是否失效。

总之,通过这种自顶向下的分析,我们能够找到系统当前的瓶颈是在哪些模块。

对于自底向上的资源视角:

我们主要从 4 个维度进行了考虑:

在磁盘方面,我们希望我们要比 Linux 的常用磁盘监控命令 iostat 更为丰富,比如除了磁盘利用率,吞吐 iops 之外,我们还想统计进程级别的磁盘读写情况和 page cache 的使用情况。

在网络方面,我们希望我们要比 Linux 的常用网络监控命令 sar 更为丰富,比如除了网络吞吐和收发包的速度之外,我们还想统计进程级别的连接个数等等。

在 CPU 方面,我们不仅要统计操作系统和进程的 CPU 利用率,还想统计 IoTDB 进程内部不同模块不同线程池的 CPU 利用率,也还想统计进程内部线程池的关键参数。...

剩余内容已隐藏

查看完整文章以阅读更多