Elasticsearch 指定特定分片进行存储或者查询

Posted rawls

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Elasticsearch 指定特定分片进行存储或者查询相关的知识,希望对你有一定的参考价值。

  Elasticsearch 项目中使用到Es的父子结构、在数据填充之后,查看每个节点的数据分布情况,发现有的节点数据多,有的节点少的情况,在未使用Es父级结构之前,每个节点的数据分布还算平均,如下图:

       技术分享图片

  左边的数据是未使用父子结构之前每个节点的数据分布数量,右边的是使用了父子结构之后的数据节点分布数量,最下面一行红色的数字是节点平均数量,可以看出,左边的数据与平均值相差不大,右边的数据与平均值最大相差400万,这个差距还是蛮大的,为什么会有这么大的差距呢?围绕着这个问题,进行了一番研究,今天就来学习学习下Elasticsearch 的路由机制。

  首先,Es的路由机制与其分片机制有着直接的关系,Es的路由机制是通过哈希算法,将具有相同哈希值的文档放置在同一分片中的,通过这个哈希算法来进行负载均衡的效果,这个就是为什么左侧图中的每个节点的数据都与平均值相差不大的原因。

  计算公式是:

shard = hash(routing) % number_of_primary_shards

  routing 值是一个任意字符串,它默认是_id但也可以自定义。这个routing字符串通过哈希函数生成一个数字,然后除以主切片的数量得到一个余数(remainder),余数的范围永远是0number_of_primary_shards - 1,这个数字就是特定文档所在的分片。

  所以,每一条数据在写入的时候,是放在分片1上,还是分片2上,不是瞎蒙的,是通过计算得来的。这也解释了为什么主分片的数量只能在创建索引时定义且不能修改:如果主分片的数量在未来改变了,所有先前的路由值就失效了,文档也就永远找不到了。

  上面解释清楚了,在来解释下,为什么我使用了Es父子结构之后,每个节点的数据发生了那么大的差距呢?

  解释这个之前,先来看下Es父子结构情况下,写入子数据的写法(怎么创建父子结构这里就不赘述了):

PUT /company/employee/1?parent=london 
{
  "name":  "Alice Smith",
  "dob":   "1970-10-24",
  "hobby": "hiking"
}

  在创建子文档的时候你必须指出他们的父文档的id,为什么要指定父文档的ID呢?这是因为Es在存储子数据的时候,会用父文档的ID去计算存放在那个分片,它会把父文档相同的数据都存放在同一个分片上面;

  举个例子,如果父文档1,下面子文档有10个,存储在A分片;

  分文档2,下面子文档有500个,存储在B分片上; 

       这样,随着每个父文档对应的子文档数据分布不均,节点的数据量就会越来越不均衡,这就说明了为什么使用了Es父子结构之后,节点数据差距较大的情况了。

 

  问题来了,那么怎么解决分布不均的问题呢?

  可以通过指定个性化路由来处理,所有的文档API(get,index,delete,update和mget)都能接收一个routing参数,可以用来形成个性化文档分片映射。一个个性化的routing值可以确保相关的文档存储到同样的分片上。

  

  参考:https://www.cnblogs.com/bonelee/p/6055340.html

  

  

 

以上是关于Elasticsearch 指定特定分片进行存储或者查询的主要内容,如果未能解决你的问题,请参考以下文章

扩展ElasticSearch:实现分片并可用于存储亿万文档的实践

Elasticsearch分布式文档存储

#yyds干货盘点# ElasticSearch第三弹之存储原理

【ES】ElasticSearch 深入分片

Elasticsearch:为自管的 Elasticsearch 添加分片分配感知

ElasticSearch中index的设计