背景
1.ES PAAS管理的集群升级了100+,从7.5升级到7.17 (保证每个大版本最终仅维护一个小版本集群)
2.由于业务使用差异大,也出了不少问题,前面的文章也有提到过Integer类型字段使用terms查询效率低的情况
3.这里再分析一个CPU、IO飙升的场景
现象
1.用户报障:“ES集群写入吞吐量变小了”
2.观察下来发现确实CPU高了,IO也有明显抖动
排查与分析
1.发现YoungGC频率变高了一些,猜测可能是G1GC的问题(我们使用JDK11重新打了ES镜像),经过版本替换,没有明显变化。
参考issue:Fix G1 GC default IHOP by henningandersen · Pull Request #46169 · elastic/elasticsearch · GitHub
这可能是另一个场景的case,经过测试,不属于我们的场景。
2.多次执行hot_threads API观察, 发现时不时会出现 update相关函数 消耗的 CPU多。
3.继续使用arthas抓取一段时间的数据,发现是 FST、DocID 读取慢
从图中可以看到Bulk请求执行过程中的getDocID方法占有大量CPU。
4.集群写多读少,使用的是niofs。可知,7.5版本的FST是在堆外,但是_id字段是在堆内。升级到7.17版本后,FST在堆外,该字段也放到了堆外(官方版本应该是7.9就开始放到堆外了)。数据放到堆外,其实也就是文件放到磁盘,读一次之后放到pagecache。
这样也就可以解释了,在upsert类请求多的时候会频繁查询docId,此时如果_id字段没有进入pageCache或者被踢出pageCache,那么就会出现响应慢,并且CPU高、IO高的情况。
5.mmapfs、hybridfs实测是什么情况暂时不明确,目前没有收到搜索类集群CPU、IO方面的报障。
测试验证
将FST、BKD等全部改成放到堆内(开源版需要改造)
可以看到,CPU有显著下降,也相对均衡。(之前蓝色线高,是因为该节点有大量的主分片)
结论
1.update、upsert、get等请求如果十分频繁,_id使用offheap将不会是个好的选择,除非给足够的堆外内存,并且保证尽可能常驻内存。
2.不同的业务场景下使用ES的同一版本也会有不一样的效果。
3.mmapfs、hybridfs在频繁update情况下,实测是什么情况暂时不明确,目前没有收到搜索类集群CPU、IO方面的报障,可能不会有这么明显的差距。(官方描述写入速度仅降低了1.8%)
4.最后吐槽一下,写入不停的情况下,translog的恢复实在是太慢了,由于大分片恢复/rebalance时,translog不会被清理,导致恢复/迁移速度急剧下降...目前各个版本也没什么好的解决方式。