elasticsearch 分布式文档存取

2018-11-12  本文已影响10人  5d44bc28b93d

主分片与副分片的交互

我们可以发送请求到集群中的任一节点。 每个节点都有能力处理任意请求。 每个节点都知道集群中任一文档位置,所以可以直接将请求转发到需要的节点上。

例如写入一个文档。请求发送到任意一个节点node1,在node1节点上有所有的分片信息。此时的node1也称之为协调节点,当node1通过文档的id可计算出该索引下的主分片在什么位置(路由),然后将请求转发给主分片,主分片处理成功后,将请求转发到其副本分片中。
路由计算公式

shard = hash(routing) % number_of_primary_shards

routing 是一个可变值,默认是文档的 _id ,也可以设置成一个自定义的值。 routing 通过 hash 函数生成一个数字,然后这个数字再除以 number_of_primary_shards (主分片的数量)后得到 余数 。这个分布在 0 到 number_of_primary_shards-1 之间的余数,就是我们所寻求的文档所在分片的位置。

这就解释了为什么我们要在创建索引的时候就确定好主分片的数量 并且永远不会改变这个数量:因为如果数量变化了,那么所有之前路由的值都会无效,文档也再也找不到了

新建索引删除文档

elas_0402.png

以下是在主副分片和任何副本分片上面 成功新建,索引和删除文档所需要的步骤顺序:

  1. 客户端向 Node 1 发送新建、索引或者删除请求。
  2. 节点使用文档的 _id 确定文档属于分片 0 。请求会被转发到 Node 3,因为分片 0 的主分片目前被分配在Node 3 上。
  3. Node 3 在主分片上面执行请求。如果成功了,它将请求并行转发到 Node 1 和 Node 2 的副本分片上。一旦所有的副本分片都报告成功, Node 3 将向协调节点报告成功,协调节点向客户端报告成功。

在客户端收到成功响应时,文档变更已经在主分片和所有副本分片执行完成,变更是安全的。

一致性问题思考:

查找文档

elas_0403.png

以下是从主分片或者副本分片检索文档的步骤顺序:

  1. 客户端向 Node 1 发送获取请求。

  2. 节点使用文档的 _id 来确定文档属于分片 0 。分片 0 的副本分片存在于所有的三个节点上。 在这种情况下,它将请求转发到 Node 2 。

  3. Node 2 将文档返回给 Node 1 ,然后将文档返回给客户端。

在处理读取请求时,协调结点在每次请求的时候都会通过轮询所有的副本分片来达到负载均衡。

在文档被检索时,已经被索引的文档可能已经存在于主分片上但是还没有复制到副本分片。 在这种情况下,副本分片可能会报告文档不存在,但是主分片可能成功返回文档。 一旦索引请求成功返回给用户,文档在主分片和副本分片都是可用的。

局部文档更新

elas_0404.png

以下是部分更新一个文档的步骤:

  1. 客户端向 Node 1 发送更新请求。
  2. 它将请求转发到主分片所在的 Node 3 。
  3. Node 3 从主分片检索文档,修改 _source 字段中的 JSON ,并且尝试重新索引主分片的文档。 如果文档已经被另一个进程修改,它会重试步骤 3 ,超过 retry_on_conflict 次后放弃。
    如果 Node 3 成功地更新文档,它将新版本的文档并行转发到 Node 1 和 Node 2 上的副本分片,重新建立索引。 一旦所有副本分片都返回成功, Node 3 向协调节点也返回成功,协调节点向客户端返回成功。

注意:当主分片把更改转发到副本分片时, 它不会转发更新请求。 相反,它转发完整文档的新版本。请记住,这些更改将会异步转发到副本分片,并且不能保证它们以发送它们相同的顺序到达。 如果Elasticsearch仅转发更改请求,则可能以错误的顺序应用更改,导致得到损坏的文档。

为什么不转发更新请求,而是转发完整的文档。

{
  "name":"zhangsan",
  "sex":"male",
  "age":18
}

假设A与B两个操作到达主分片,A 操作修改name为lisi、性别female,B操作修改age为20、性别male ,同时转发A请求到副本分片,然后转发请求B操作到副本分片。由于请求时异步的,我们假设A先到达B后到达(与主分片更新循序一直)

{
 "name":"lisi",
 "sex":"female",
 "age":18
}
{
  "name":"lisi",
  "sex":"male",
  "age":20
}
转发请求方式处理
{
  "name":"zhangsan",
  "sex":"male",
  "age":20
}

{
  "name":"lisi",
  "sex":"female",
  "age":18
}

这样也就造就了副本分片的顺序与主分片不一致,所以文档也就破坏了

检索文档一致性问题

通过以上描述,我们知道主分片与副本分片都是可以进行检索的,那么当文档_id为xx的文档被更新时,同时我们在检索_id为xx的文档时会不会检索到还未更新的文档呢?理论上来讲是会出现这种情况的。

上一篇 下一篇

猜你喜欢

热点阅读