shard
确定shard的公式:
shard = hash(routing) % number_of_primary_shards
routing 默认是文档的 _id ,也可以设置成一个自定义的值。
因此要在创建索引的时候就确定好主分片的数量,并且永远不会改变这个数量,因为如果数量变化了,那么所有之前路由的值都会无效。
每个节点都知道集群中任一文档位置,所以可以直接将请求发到任意节点。当然,为了扩展负载,更好的做法是轮询发送集群中所有的节点。
shard、replica同步
新建、索引或者删除请求
步骤:
- 户端向 Node 1 发送新建、索引或者删除请求。
- 节点使用文档的 _id 确定文档属于shard 0 。请求会被转发到 Node 3(因为shard 0 被分配在 Node 3 上)。
- Node 3 在shard 0上面执行请求。如果成功了,它将请求并行转发到 Node 1 和 Node 2 的replica R0上。一旦所有的R0都报告成功, Node 3 将向Node 1报告成功,Node 1向客户端报告成功。
查询请求
步骤:
- 客户端向 Node 1 发送查询请求。
- node 1使用文档的 _id 来确定文档属于shard 0 。replica 0 存在于Node 1、Node 2上。 这种情况下,每次请求都会轮询路由Node 1、Node 2,这里假设路由到Node 2。
- Node 2将文档返回给Node 1 ,然后Node 1将文档返回给客户端。
注意:
在文档被检索时,已经被索引的文档可能已经存在于shard上但是还没有复制到replica。即强一致性无法保证,但最终一致性可以保证。
更新请求
POST /{index}/{type}/{id}/_update
步骤略。
注意:
Node 3 从P0检索文档,修改 _source 字段中的 JSON ,并且尝试重新索引主分片的文档。 如果文档已经被另一个进程修改(_version冲突),它会重试步骤 3 ,超过 retry_on_conflict 次后放弃。
如果 Node 3 成功地更新文档,它将新版本的文档并行转发(新建、索引或者删除请求的步骤里转发的是请求而不是文档)到 Node 1 和 Node 2 上的R0,重新建立索引。一旦所有R0都返回成功,Node 3 向Node 1返回成功,Node 1向客户端返回成功。
为什么要转发文档而不是请求?
因为转发请求是异步的,不能保证到达replica的顺序,若转发更新请求,则可能以错误的顺序应用更改,导致得到损坏的文档。而转发文档,则replica可以直接根据_version来获取最大版本号的文档。
批量请求(_mget 、_bulk)
bulk步骤:
- 客户端向 Node 1 发送 bulk 请求。
- Node 1 为每个命中的shard创建一个批量请求,并将这些请求并行转发到每个包含该shard的节点。
- shard按顺序(请求报文体中的子请求顺序)执行每个操作。当一个子请求操作成功时,shard并行转发新文档(或删除)到replica,然后执行下一个子请求。 一旦所有的子请求的replica向shard报告完成(无论执行是否成功),该shard将向node 1报告,node 1将这些响应收集整理并返回给客户端。
可选的请求参数
-
consistency
解决分布式脑裂问题,参数的值可以设为 one (只要该index的shard状态 ok 就允许执行_写_操作),all(必须要该index的shard和多个replica的状态没问题才允许执行_写_操作), 或 quorum (默认值)。
# quorum 即大于一半的分片,注意,number_of_replicas是primary shard对应的replica数量,不是全部replica数量 int( (primary + number_of_replicas) / 2 ) + 1
注意:新索引默认有 1 个replica,这意味着为了满足consistency至少需要两个活动的node。 这就会阻止我们在单一node上做任何事情。为了避免这个问题,ES要求只有当 number_of_replicas 大于1的时候,consistency策略才会执行。
-
timeout
如果没有足够的replica,Elasticsearch会等待,直到满足consistency策略。默认最多等待1分钟。 你可以使用 timeout 参数 使它更早终止: 100 是100毫秒,30s 是30秒。
一个Lucene索引在Elasticsearch称作shard。 一个Elasticsearch索引是shard的集合。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。