上周我们的一个项目准备接受第一阶段的验收时,结果就在这个关键的节骨眼上,大屏大部分数据指标显示突然都「黑」了,任凭鼠标再怎么刷新,都没有用。
很明显,后台出事了。
像这种「数据不能及时供应」的问题,排查链路一般都是这样的:提供数据的微服务 -> 存储数据的数据库 -> 计算该数据的进程 -> 进程上游的数据源。
一级级跟爬楼梯一样挨个排查,先是确保微服务没挂,日志没有异常;接着就是看存储该数据的数据库表里,有没有最新的数据,结果就是这么一查,查出问题了。
一、问题表现
来,先看个截图。
吓人不?
这就是我在查对应后台数据表时,发现查询结果一直在那里转圈圈出不来后,逐个向每台 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 来说,因为它特殊的集群组织形式,在某些时候,需要花费的运维成本,确实要高那么一丢丢。
如果字段的最大可能长度超过255字节,那么长度值可能…
只能说作者太用心了,优秀
感谢详解
一般干个7-8年(即30岁左右),能做到年入40w-50w;有…
230721