ClickHouse 被干冒烟了,咋整?

安瑞哥是码农 2025-02-03 10:48:00
这是一个发生在我生产环境的真实案例。

 

上周我们的一个项目准备接受第一阶段的验收时,结果就在这个关键的节骨眼上,大屏大部分数据指标显示突然都「黑」了,任凭鼠标再怎么刷新,都没有用。

 

很明显,后台出事了。

 

像这种「数据不能及时供应」的问题,排查链路一般都是这样的:提供数据的微服务 -> 存储数据的数据库 -> 计算该数据的进程 -> 进程上游的数据源。

 

一级级跟爬楼梯一样挨个排查,先是确保微服务没挂,日志没有异常;接着就是看存储该数据的数据库表里,有没有最新的数据,结果就是这么一查,查出问题了。

 

一、问题表现

 

来,先看个截图。

 

 

吓人不?

 

这就是我在查对应后台数据表时,发现查询结果一直在那里转圈圈出不来后,逐个向每台 clickhouse 服务器查看系统负载时发现的。

 

负载居然给干到了 2K+,而且这里是纯纯的 CPU 消耗。

 

这里插播个冷知识:

 

当看到系统负载过高时,有时不一定就是 CPU 被使的太狠导致的,如果系统出现了过多的 IO 等待操作,这个负载也会很高,但这一点,会通过「 IO 等待」这个指标反映出来,也就是截图第 3 行的那个 wa 指标。

 

如果这个 wa 的值不为 0,说明当前的 IO (网络 IO,或者磁盘 IO,或者两者兼而有之)出现了瓶颈,需要着手这个方面的优化。

 

而当前这个 wa 值为 0 ,或是接近 0,那就代表只是纯纯的 CPU 消耗。

 

再来瞅一眼,是哪个进程这么凶残,把这台服务器给榨成这样:

 

 

真凶果然就是我 clickhouse(下称 CK) 大宝贝。

 

要知道,当前这只是一台 64 核,单核单线程 CPU 的服务器。

 

 

理论上它的满荷负载,就是 64,而现在却是飙到了 2700+,足足超出满载的 400 多倍。

 

这就好比一辆只能拉 1吨货的汽车,你硬是给它压了 400多吨的重量,那不得干冒烟了呀。

 

二、揪出内鬼

 

根据我的经验,一般集群如果出现「慢」的问题,大概率都可能是其中的「某一台」机器出现了问题,但根据木桶原理,往往就是这么一个害群之马,会拖慢整个集群的效率。

 

只要是数据库,这种解决套路都大差不差,负载高,无非就是当前节点产生了很多不合理的读写操作。

 

那对于 CK 来说,该怎么把这些不合理的操作给揪出来呢?

 

CK 提供了两张很好用的,记录数据库操作的系统表。

 

一张叫:system.processes;

 

另一张叫:system.query_log。

 

 

网上看到了很多关于这两张表的用法,也试过一些,但是因为查询逻辑比较复杂(各种 join 跟函数嵌套使用),导致跑了好久,结果都出不来。

 

要知道,如果你当前 CK 机器本身负载就很高了,你再去执行一个逻辑复杂的 SQL,导致负载进一步增加,执行效率只会更低(甚至压根跑不出结果),那不就陷入死循环了嘛。

 

所以正确的玩法,一定是只需要执行一个非常简单的 SQL,就能把那些「资源消耗大户」给揪出来。

 

怎么玩?

 

根据我这次的经验,执行这个 SQL 就够了(连排序都不用)。

 

 

虽然负载很高,但因为这个 SQL 足够的简单,所以很快结果就能跑出来。

 

 

CK 很聪明,默认情况下,这个结果会根据 SQL 执行消耗的时间,从大到小排序。

 

所以,你一眼就能看出,是哪些 SQL 导致的当前负载过高。

 

三、怎么解决

 

问题找到了,怎么解决就好办了。

 

第 1 步:找到对应的,执行这个 SQL 的人,一起看看这个 SQL 写的是不是很傻逼,查询方式对不对,有没有有效利用索引等;

 

第 2 步: 这些导致高负载的 SQL,肯定不能让它继续执行了,根据上面找出来的 query_id,把它们挨个 kill 掉;

 

 

第 3 步:有时候就算把这些 SQL 暂时 kill 掉了,但过不了一会,因为后台调度的原因,又会跑起来,导致系统负载再次飙升,这个时候,一个聪明的做法,就是把这些查询涉及到的表给直接「下线」(这个设计很高明)。

 

这一次,我就是根据这「3 步走」策略,暂时稳住了整个项目。

 

其实这台服务器的「慢」,我心里是有数的,为了方便,在每次使用 CK 时,我都用客户端直接连的这台机器,这就导致一些数据量不大的表(千万级以下),我都用的「本地表」,而这些本地表,我又刚好都建在了这一台机器上。

 

所以就导致,跑在这台服务器上的 CK 实例,默默承受了超出其他几个实例,N 倍的压力。

 

至于怎么彻底解决这个问题?

 

1、调整一些不合理 SQL 的写法,傻逼写法改成科学合理的写法,该加索引加索引,不需要的字段能不查就不查;

 

2、把分片表的准入门槛降低,稍微大一点,且使用频率高的表,都尽量优化为分片表,让原来只在一台机器上的压力,给分摊到多台机器上;

 

3、所有那些数据量比较小的本地表,给尽可能平均挪到多台机器上,不要只薅一台服务器的羊毛。

 

四、最后

 

经过这么一系列的组合拳下去,这台曾经被干冒烟的服务器,终于恢复了往日该有的平静(负载一直控制在 30 左右)。

 

其实面对这样的「慢」问题,所有的数据库解决套路都非常类似。

 

只不过对于 CK 来说,因为它特殊的集群组织形式,在某些时候,需要花费的运维成本,确实要高那么一丢丢。

 

作者丨 Anryg(安瑞哥)
来源丨公众号: 安瑞哥是码农(ID:gh_c12dc29ae2e7
dbaplus社群欢迎广大技术人员投稿,投稿邮箱:editor@dbaplus.cn
最新评论
访客 2024年04月08日

如果字段的最大可能长度超过255字节,那么长度值可能…

访客 2024年03月04日

只能说作者太用心了,优秀

访客 2024年02月23日

感谢详解

访客 2024年02月20日

一般干个7-8年(即30岁左右),能做到年入40w-50w;有…

访客 2023年08月20日

230721

活动预告