一个索引引发的血案

作者:掠影
最后编辑时间:2018-09-07 14:48:35
浏览次数:1251



索引引发的血案

起因

最近在做电商搜索结果爬虫,以及对应的数据展示界面;功能完成后就部署上线,并设置了定时抓取数据的计划任务;本以为可以顺利运行(毕竟数据量和并发量也不大),没想到三天里竟然连续出现多次服务器Timeout的事件;让人着实挠头

背景介绍

由于PHP的单线程特性,每次抓取数据(网络请求)的同步过程中利用这段周期来进行连接数据库并进行更新(实际上通过异步的回调过程是可以做到等待让权的,后续更新这一方式);这就限制了爬虫的效率,故而采用了多进程的方式,利用PHP的pcntl特性,将需要抓取的列表作为fork前的公共变量,fork出多个子进程的方式进行并行抓取;在抓取过程中,意外地发现clickhouse的客户端频繁报timeout的错误,然而连接实际上是在本机进行的(server绑定0.0.0.0) ,故而必然是服务器端出了问题;

排查

  1. 首先检查clickhouse-server的资源使用情况:通过top检查了当时的服务器运行情况,发现故障产生时,clickhouse-server进程本身占用的CPU和内存都处于常数级,并未出现峰值;
  2. 其次查询服务端日志,发现问题在error log中,clickhouse-server无法写入输出流;既然并不是服务本身的问题,又无法进行I/O,那么问题必然出在服务器本身,或者是其上的其他服务上;
  3. 继续排查问题,意外地发现MySQL的CPU占用率达到了300%,甚至峰值到500%;这本身也是一个异常情况,由于服务器上的MySQL大多是作为日志存储用,不大可能由于过高的并发访问而宕机;于是带着这样的疑问,执行了show processlist;指令
  4. 问题就这样暴露了出来,爬虫运行过程中的一个查询语句占用了大量的CPU,甚为吓人;突然反应过来这是一个varchar字段的查询,而这一字段本身具有市场唯一性(单市场上所有商品都独有的Unique ID),故而直接查询时速度趋向于全表扫描,占用了大量的CPU做I/O调度;同时又因为5核并行的机制,导致了查询时频繁的全表扫描,使得服务器最终来不及处理I/O而CPU飙升;
  5. 最终通过一个简单的ALTER TABLE ADD INDEX的操作,加上了索引字段,瞬间负载就降了下来,心情愉悦;

总结

  1. 面对数据库响应异常的情况时,首先检查服务本身是否出现过高的占用,若出现异常则需要检查相应问题,或修复bug或调整配置参数
  2. 其次,若本身状态没问题,则可以考虑同服务器上其他服务的影响,诸如本例中出现的MYSQL服务CPU过高,通过排查同地服务出现的问题来迂回解决

取消

感谢您的支持,我会继续努力的!关闭

扫码支持
大家有钱的捧个钱场,没钱的捧个人场233333

打开支付宝扫一扫,即可进行扫码打赏哦

分享到: QQ空间 更多



评论区