路由
当索引一个文档的时候,文档会被存储到一个主分片中。
shard = hash(routing) % number_of_primary_shards
routing 是一个可变值,默认是文档的 _id ,也可以设置成一个自定义的值。 routing 通过 hash 函数生成一个数字,然后这个数字再除以 number_of_primary_shards (主分片的数量)后得到 余数 。这个分布在 0 到 number_of_primary_shards-1 之间的余数,就是我们所寻求的文档所在分片的位置。
所以创建索引要确定分片数量,且永远不会更改。如果分片数量改变了,所有之前的路由值都无效,无法找到文档了。
主副分片交互
假设一个集群它包含一个叫 blogs 的索引,有两个主分片,每个主分片有两个副本分片。相同分片的副本不会放在同一节点, 如下图。
image我们可以发送请求到集群中的任一节点。 每个节点都有能力处理任意请求。 每个节点都知道集群中任一文档位置,所以可以直接将请求转发到需要的节点上。 在下面的例子中,将所有的请求发送到 Node 1 ,我们将其称为 协调节点(coordinating node) 。
注: 新建、索引和删除 请求都是 写 操作, 必须在主分片上面完成之后才能被复制到相关的副本分片。
新建、索引、删除一个文档
image- 客户端向
Node 1
发送新建、索引或者删除请求 - 节点使用文档的 _id 确定文档属于分片 0 。请求会被转发到
Node 3
,因为分片 0 的主分片目前被分配在Node 3
上。 -
Node 3
在主分片上面执行请求。如果成功了,它将请求并行转发到Node 1
和Node 2
的副本分片上。一旦所有的副本分片都报告成功,Node 3
将向协调节点报告成功,协调节点(Node 1
)向客户端报告成功。
在客户端收到成功响应时,文档变更已经在主分片和所有副本分片执行完成,变更是安全的。
读操作
可以从主分片或者从其它任意副本分片检索文档
image- 客户端向
Node 1
发送获取请求 - 节点使用文档的 _id 来确定文档属于分片 0 。分片 0 的副本分片存在于所有的三个节点上。 在这种情况下,它将请求转发到
Node 2
-
Node 2
将文档返回给Node 1
,然后将文档返回给客户端
在处理读取请求时,协调结点在每次请求的时候都会通过轮询所有的副本分片来达到负载均衡。
注:在文档被检索时,已经被索引的文档可能已经存在于主分片上但是还没有复制到副本分片。 在这种情况下,副本分片可能会报告文档不存在,但是主分片可能成功返回文档。 一旦索引请求成功返回给用户,文档在主分片和副本分片都是可用的
更新操作
image- 客户端向
Node 1
发送更新请求 - 它将请求转发到主分片所在的
Node 3
-
Node 3
从主分片检索文档,修改_source
字段中的 JSON ,并且尝试重新索引主分片的文档。 如果文档已经被另一个进程修改,它会重试步骤 3 ,超过retry_on_conflict
次后放弃 - 如果
Node 3
成功地更新文档,它将新版本的文档并行转发到Node 1
和Node 2
上的副本分片,重新建立索引。 一旦所有副本分片都返回成功, Node 3 向协调节点也返回成功,协调节点(Node 1
)向客户端返回成功
多文档模式
elas_0405.png使用 mget 取回多个文档
- 客户端向
Node 1
发送 mget 请求 -
Node 1
为每个分片构建多文档获取请求,然后并行转发这些请求到托管在每个所需的主分片或者副本分片的节点上。一旦收到所有答复,Node 1
构建响应并将其返回给客户端。
使用 bulk 修改多个文档
- 客户端向 Node 1 发送 bulk 请求
-
Node 1
为每个节点创建一个批量请求,并将这些请求并行转发到每个包含主分片的节点主机 - 主分片一个接一个按顺序执行每个操作。当每个操作成功时,主分片并行转发新文档(或删除)到副本分片,然后执行下一个操作。 一旦所有的副本分片报告所有操作成功,该节点将向协调节点报告成功,协调节点将这些响应收集整理并返回给客户端
网友评论