背景
- 13号有一个大上线,其中一个功能就是排序功能,说复杂也不复杂,说难吧也不难,但是麻烦的就是加上Sort之后速度奇慢无比。
- 排序实现也不太复杂,基本都是基于function score + sort 实现,对应不同的商品品类,有不同的排序规则(Hmm,目前还没有上个性化排序。。),实现方式就是定位品类之后,用function score进行提升部分商品的score,在这之后用sort进行【score + field1 +field2】的排序,看着也不复杂对吧。
- ES机器配置不太高(qiong…..)4C 8G * 3,索引中在售商品也不太多几,万的样子,分布到200多个城市站,总共合起来大概千万出头的数据(有部分非在售商品)。
问题
- 每次定位到品类之后,使用了品类排序【score + field1 +field2】,速度奇慢无比,平时几十毫秒的查询能变成5-6秒甚至更多,有点让人无法忍受
尝试过程
- 最开始打算用缓存解决问题,但是更新频率实在有点高的不行。。这个有点扛不住。
- 后来打算按照城市站分索引,这样一个索引数据量就很小了,排序应该就不是什么大问题了,但是查询有点麻烦。
- 先reindex一个小的索引,试了试排序速度,果然恢复到了几十毫秒的数量级了。
突然想到了也许多加一些分片也可以解决这个问题,毕竟我们是有城市站routing的啊。 - 不过城市站反正是查询的必须条件已经加上了routing,吧shard从默认的5个先加到了50个,试了一下果然速度提升到100ms左右,再往上加shard的时候发现了另外一个问题,大批量的出现ESReject问题,可能是一次bulk或者index数据的量略大,ES又需要进行routing的原因吧,最终上线的时候,保守一点使用了40 Shard,目前速度尚在可接受范围(线上最起码是8c 16G的。。),如果想在提升速度,估计要加机器了(还是那句话。。。qiong。。。)
加速原理
- 没看源码,纯属自己猜测:
- 感觉shard和分索引应该差不多,Es Query需要找到对应的shard,拽出来符合条件的数据进行排序,然后输出出去。拽出来数据应该是在shard内部进行过排序,如果shard内部文档过多,速度应该会比较慢。
- 我们这边业务场景是城市站必须有,而且文档按照城市站分开后相对来说很平均了(当然还是有部分shard很小。。),将shard数量提高以后,shard内部排序的文档数量少了很多,速度自然就上去了。
- shard过多,在ES进行bulk插入数据时候,routing到对应分片,这步骤应该会花较多时间,如果机器配置不太给力的话(囧。。比如说我们),shard数量还是不要太多,否则机器负载会很高很高(前两天看到负载破20了 - -!还好只是瞬时)