说明
本文描述问题及解决方法同样适用于 腾讯云 Elasticsearch Service(ES)。
- 系统环境说明
Linux环境:CentOS Linux release 7.2 (Final)
Elasticsearch: 7.10.1
Java:1.8.0_181
- 机器配置
机器数量:6
内存:64G
硬盘:2T
CPU核心数:32
背景
众所周知,当业务写入量很大的时候,如果索引分片分布得不均衡,大概率会发生bulk reject。这是由于分片设计不合理,没有均匀分布到所有节点,无法充分利用Elasticsearch分布式架构的特性,请求全部集中到了个别节点,压力无法分散,进而导致的写入拒绝。
问题
对于背景中介绍的场景,本文则不做过多介绍。这里我们关注的是另外一种情况:
当ES集群所有索引分片设计合理的前提下,分片分布很均衡,但是还是有个别节点发生了写入拒绝。这种问题就比较奇怪,需要深入排查一下。
通过业务监控到的失败率,结合写入拒绝率,可以确认判断业务失败是由bulk reject引起的。
问题原因
通过排查发现,reject全部集中在一个节点:
回溯历史队列情况,也发现只有个别节点容易超过write queue的最大值(1024):
所以这里我第一时间怀疑是业务有指定分片写入的行为,通过确认,发现6块分片只有1块有数据,果不其然:
然后通过进一步确认,发现每条数据都指定了routing。而routing的值全文只有一个,所以routing的不合理设计就是造成问题的罪魁祸首。
解决方案
改造业务改变routing逻辑为随机值,或者不指定routing写入,才能解决该问题。
上图为改造之后的CPU监控,可以看到效果还是很明显的。CPU使用率从9号业务改造之后,各节点之间表现得更加均匀,没再有明显的热点。
bulk reject从9号之后,也再也没有发生过,问题解决。
总结
业务指定routing进行写入,当routing设计不合理时,会出现大部分routing值都是重复的,会使所有请求都被转发到同一个节点,直接导致个别节点写入队列被打满、其他队列都很空闲的现象。所以,合理的分片设计固然重要,合理的routing设计也不能忽视,不然都会引起写入拒绝。