对于分析性大数据存储系统来说,在业界有个很普遍的认识,类似大数据Greenplum,Postgrasql ,Clickhouse等存储系统不支持高并发写入和读取。因此使用这类的大数据存储系统都需特别注意一些使用问题,避免集群服务不可用。
我们线上的业务曾经出现过一两次线上CPU突然暴涨接近100%,造成服务不可用的状态。下面我就来简述一下出现两次CPU突增接近100%的问题和原因。
类似这样的图,线上业务出现过两次。
关于出现这样的问题,一般我查询问题的思路是这样的,参考如下的步骤:
- 确认是否有新业务或者新活动上线
- 确认是否有新功能新需求上线
- 通过system.process或者show processlist命令查询clickhouse集群,确认执行的sql是否有问题,是否极大占用CPU资源或者内存
- 通过system.query_log定位占用CPU超过多少秒以上的sql,通过执行的sql时间和业务的日志来验证是否在此段时间占用CPU比较高
- 通过业务日志确认定位的sql是否正确
为什么处理问题的步骤是这样的呢?可能有同学会说,这都cpu都快100%,写入都会存在问题,其实并不是这样,cpu没有达到100%,写入其实是完全能保证的,简单的统计也是可以执行的,只是相对耗资源的计算则会受影响。
第一次cpu暴涨问题查证
某一天发现cpu突然暴涨,但是也没有达到100%,当时通过上诉方式,发现一个简单的update操作一直在执行,但是其实就是根据user_id更新user_name而已,只是当时有20w的数据需要修复。一个sql:
代码语言:javascript复制alter table user update set username = 'xxx' where user_id = 11;
只要持续执行这样的sql会一直占用cpu。
第二次cpu暴涨问题查证
某一天也是上面的图,cpu突然暴涨但是没有到100%,经过和业务以及运维确认没有新活动以及新需求,我开始定位clickhouse的当前执行的sql,收集一段时间也没有发现特别的问题,然后我开始分析query_sql的日志,查询凌晨3点有什么sql在执行会造成cpu占用这么高,我主要通过query_sql里面的ProfileEvents.Names和ProfileEvents.Values这两列,通过看cpu占用时间长来确定占用量大。这两列里面又需要找到OSCPUVirtualTimeMicroseconds字段(占用cpu耗时),如果是查找内存可以用memory_usage字段。查找超过10s占用cpu的sql,最后形成的sql如下:
代码语言:javascript复制select query_start_time,query_id,memory_usage,ProfileEvents.Names,ProfileEvents.Values,indexOf(ProfileEvents.Names,'OSCPUVirtualTimeMicroseconds'),arrayElement(ProfileEvents.Values,indexOf(ProfileEvents.Names,'OSCPUVirtualTimeMicroseconds'))/1000000 from system.query_log where arrayElement(ProfileEvents.Values,indexOf(ProfileEvents.Names,'OSCPUVirtualTimeMicroseconds'))/1000000 > 10 and query_start_time >= '2020-03-24 05:54:41' and query_start_time <= '2020-03-24 06:54:41' order by event_time desc limit 20 FORMAT Vertical;
查询结果如下(只是展示个例子):
通过这个sql成功找到占用耗时的sql,后面通过查询业务日志,发现后台有个bug,造成了一个死循环,一个分页查询的逻辑一直在跑着。通过找到了问题,把一直在执行的sql处理一下,cpu立马降下来了,这样问题解决了。
总结:
1:关于cpu占用100%的问题,要避免在线上对大表执行update操作
2:关于查询的sql,最好设置查询超时时间,这样避免一个sql执行需要很长时间一直占用cpu
关于上面的问题,欢迎大家一起来讨论~