首发于龙猫小组
关于elasticSearch中路由的一些问题

关于elasticSearch中路由的一些问题

近日放缓了elasticSearch的学习,老大问到了之前他看到的一个路由相关的问题,一时没有详细思路,之后查找实践后有了一定猜测,在老大的提醒下也算是明确了问题原因,在此记录下。


遇到的问题

在官方文档的getAPI描述中,有如下图的一个描述。

大体意思就是说如果指定路由查询时,指定路由是错误的,那么是不会有文档被获取到的。当时没有细想,但是直到遇到老大提的这个问题,突然发现指定错误依然有可能获取到文档,进而亲自尝试后发现以下两个问题。

  • 在指定路由存储查询时,不同路由查找到了相同ID的文章。
  • 在指定路由创建和不指定路由创建时,查找得到了相同ID的两个文档

具体实例,在7.x的版本上,指定路由A存储的数据,在指定路由B查询的时候也查找到了相应数据。但是,同样的存储和查询方式在5.6版本上尝试后没有出现这种情况,这里给出两张图可以更直观地比较下:

7.x版本

5.6版本

可以看到,确实如图所示,相同存储、查询方式下,两个版本有不一样的结果。与此同时,在5.6版本存储相同ID的带routing的和不带routing的文档数据(数据相同),结果如下图,

如图,他会形成两个相同ID的文档,这会破坏ID的唯一性,进而引发其他查询问题。

原因分析

为什么会出现这样的问题呢,乍一看有点蒙,但其实细细捋一捋就可以得出大致的思路。

首先问题出现在routing参数上,那就去仔细查查这个参数是干什么的,怎么实现的。

这是官方文档的解释,说白了他就是查询时找文档的一个小索引,我们知道elasticSearch中文档是存储在不同分片上的,那文档和和分片就需要一个对应关系了,路由的作用就是如此,他可以指定,也可以默认为_id,通过elasticSearch底层的hash方法对主分片数取余即可得到具体落在哪个分片上。

到这里其实思考认真一些的话,也就能找到问题的产生原因了,既然是一个找到了,一个没找到,searchall也是可以看到数据是有正确存进去的,那就一定是没查对地方,也就是上面公式中shard_num 不对,而_routing是一样的,所以num_primary_shards即索引主分片数出现了不同。那这样就去看下两个版本之间对于这个数字的设定,发现5.6默认的配置是5主,而7.x则开始变为1主,5.6中把数据路由到了其他分片,而7.2默认只有一个主分片,则无论怎么路由也就是那一个分片上了,这也就是本来如5.6那样不该被查到的文档,也被查到了的原因。

至于第二个问题,同一ID的文档出现两个版本,其实往后看routing的文档也会发现一个说明( 看的不仔细)

可以看到他是有说路由可能导致无法保证文档ID依然是唯一id,这个问题也需要在创建索引时多加注意。

后记

这个问题其实还是之前看一些基础知识的时候没有更加仔细地实践导致的,对文档某些标注的思考也不到位,还是要实践出真知啊!

编辑于 2020-03-15 16:50