Elasticsearch 分片交互过程分析

系统 1668 0
1 Elasticseach 如何将数据存储到分片中

问题:当我们要在 ES 中存储数据的时候,数据应该存储在主分片和复制分片中的哪一个中去;当我们在 ES 中检索数据的时候,又是怎么判断要查询的数据是属于哪一个分片。

 

  • 数据存储到分片的过程是一定规则的,并不是随机发生的。

 

  • 规则: shard = hash(routing) % number_of_primary_shards

 

  • Routing 值可以是一个任意的字符串,默认情况下,它的值为存数数据对应文档  _id  值,也可以是用户自定义的值。 Routing 这个字符串通过一个 hash 的函数处理,并返回一个数值,然后再除以索引中主分片的数目,所得的余数作为主分片的编号,取值一般在 0 number_of_primary_shards - 1 的这个范围中。通过这种方法计算出该数据是存储到哪个分片中。

 

  • 正是这种路由机制,导致了主分片的个数为什么在索引建立之后不能修改。对已有索引主分片数目的修改直接会导致路由规则出现严重问题,部分数据将无法被检索。

 

2 、主分片与复制分片如何交互

为了说明这个问题,我用一个例子来说明。

Elasticsearch 分片交互过程分析  

在上面这个例子中,有三个ES node ,其中每一个 index 中包含两个 primary shard ,每个 primary shard 拥有一个 replica shard 。下面从几种常见的数据操作来说明二者之间的交互情况。

 

  1. 索引与删除一个文档

Elasticsearch 分片交互过程分析  

 

这两种过程均可以分为三个过程来描述:

阶段 1 :客户端发送了一个索引或者删除的请求给 node 1

 

阶段 2 node 1 通过请求中文档的  _id  值判断出该文档应该被存储在 shard 0  这个分片中,并且 node 1 知道 shard 0 primary shard 位于 node 3 这个节点上。因此 node 1 会把这个请求转发到 node 3

 

阶段 3 node 3 shard 0  primary shard 上执行请求。如果请求执行成功,它 node 3 将并行地将该请求发给 shard 0 的其余所有 replica shard 上,也就是存在于 node 1 node 2 中的 replica shard 。如果所有的 replica shard 都成功地执行了请求,那么将会向 node 3 回复一个成功确认,当 node 3 收到了所有 replica shard 的确认信息后,则最后向用户返回一个 Success 的消息。

 

  1. 更新一个文档

Elasticsearch 分片交互过程分析  

 

该过程可以分为四个阶段来描述:

阶段 1 :客户端向 node 1 发送一个文档更新的请求。

 

阶段 2 :同样的 node 1 通过请求中文档的  _id  值判断出该文档应该被存储在 shard 0  这个分片中,并且 node 1 知道 shard 0 primary shard 位于 node 3 这个节点上。因此 node 1 会把这个请求转发到 node 3

 

阶段 3 node 3 从文档所在的 primary shard 中获取到它的 JSON 文件,并修改其中的 _source 中的内容,之后再重新索引该文档到其 primary shard 中。

 

阶段 4 :如果 node 3 成功地更新了文档, node 3 将会把文档新的版本并行地发给其余所有的 replica shard 所在 node 中。这些 node 也同样重新索引新版本的文档,执行后则向 node 3 确认成功,当 node 3 接收到所有的成功确认之后,再向客户端发送一个更新成功的信息。

 

 

  1. 检索文档

CRUD 这些操作的过程中一般都是结合一些唯一的标记例如: _index _type ,以及 routing 的值,这就意味在执行操作的时候都是确切的知道文档在集群中的哪个 node 中,哪个 shard 中。

而检索过程往往需要更多的执行模式,因为我们并不清楚所要检索的文档具体位置所在, 它们可能存在于 ES 集群中个任何位置。因此,一般情况下,检索的执行不得不去询问 index 中的每一个 shard

但是,找到所有匹配检索的文档仅仅只是检索过程的一半,在向客户端返回一个结果列表之前,必须将各个 shard 发回的小片的检索结果,拼接成一个大的已排好序的汇总结果列表。正因为这个原因,检索的过程将分为查询阶段与获取阶段( Query Phase and Fetch Phase )。

 

  • Query Phase

在最初的查询过程中,查询请求会广播到 index 中的每一个 primary shard replica shard 中,每一个 shard 会在本地执行检索,并建立一个优先级队列( priority queue )。这个优先级队列是一个根据文档匹配度这个指标所排序列表,列表的长度由分页参数 from size 两个参数所决定。例如:

Elasticsearch 分片交互过程分析  

 

下面从一个例子中说明这个过程:

Elasticsearch 分片交互过程分析  

Query Phase 阶段可以再细分成 3 个小的子阶段:

子阶段 1 :客户端发送一个检索的请求给 node 3 ,此时 node 3 会创建一个空的优先级队列并且配置好分页参数 from size

 

子阶段 2 node 3 将检索请求发送给该 index 中个每一个 shard (这里的每一个意思是无论它是 primary 还是 replica ,它们的组合可以构成一个完整的 index 数据)。每个 shard 在本地执行检索,并将结果添加到本地优先级队列中。

 

子阶段 3 :每个 shard 返回本地优先级序列中所记录的 _id sort 值,并发送 node 3 Node 3 将这些值合并到自己的本地的优先级队列中,并做全局的排序。

 

  • Fetch Phase

Query Phase 主要定位了所要检索数据的具体位置,但是我们还必须取回它们才能完成整个检索过程。而 Fetch Phase 阶段的任务就是将这些定位好的数据内容取回并返回给客户端。

 

同样也用一个例子来说明这个过程:

Elasticsearch 分片交互过程分析  

Fetch Phase 过程可以分为三个子过程来描述:

子阶段 1 node 3 获取了所有待检索数据的定位之后,发送一个 mget 的请求给与数据相关的 shard

 

子阶段 2 :每个收到 node 3 get 请求的 shard 将读取相关文档 _source 中的内容,并将它们返回给 node 3

 

子阶段 3 :当 node 3 获取到了所有 shard 返回的文档后, node 3 将它们合并成一条汇总的结果,返回给客户端。

 

Elasticsearch 分片交互过程分析


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论