1、Elasticsearch 增删改内部原理
下面直接点,先描述一下一个增删改请求打过来 Elasticsearch 内部做了什么。
如图
(1)对于客户端首先会选择一个节点 node 发送请求过去,这个节点 node 就是协调节点 coordinating node
(2)协调节点 coordinating node 会对 docuemnt 数据进行路由,将请求转发给对应的 node(含有 primary shard)
(3)实际上 node 的 primary shard 会处理请求,然后将数据同步到对应的含有 replica shard 的 node
(4)协调节点 coordinating node 如果发现含有 primary shard 的 node 和所有的含有 replica shard 的 node 都搞定之后,就会返回响应结果给客户端
下面手工画图展示一下上面的过程:
假设我们有 2 个节点,5 个 primary shard replica=1
1、客户端发送增删改请求给协调节点 node2
2、协调节点 node2 将请求路由到含有 primary shard 的 node1
3、node1 处理请求,并同步数据到对应的含有 replica shard 的 node2
4、协调节点 node2 如果发现含有 primary shard 的 node1 以及所有含有 replica shard 的 node2 都搞定了,就会返回响应结果给客户端
2、写一致性机制(已经被移除,替换为 wait_for_active_shards)
consistency
默认情况下,主分片需要法定数量或大部分的分片副本(其中分片副本可以是主分片或副本分片)在尝试写入操作之前可用。这是为了防止将数据写入网络分区的“wrong side”。法定人数定义如下:
int((primary + number_of_replicas)/ 2)+ 1
允许的值 consistency 是 one(仅主要分片),all(主要和所有副本),或默认 quorum 或大多数分片副本。
请注意,它 number_of_replicas 是索引设置中指定的副本数,而不是当前活动的副本数。如果您已指定索引应具有三个副本,则仲裁将如下所示:
int((primary + 3 replicas) / 2 ) + 1 = 4
但是,如果仅启动两个节点,则将没有足够的活动分片副本来满足仲裁,并且您将无法索引或删除任何文档。
timeout
如果可用的分片副本不足,会发生什么?Elasticsearch 等待,希望会出现更多的分片。默认情况下,它将等待最多 1 分钟。如果需要,可以使用 timeout 参数让它更快地中止:100 是 100 毫秒,30s 是 30 秒。
注意
默认情况下,新索引具有一个副本,这意味着应该需要两个活动分片副本以满足需要的 quorum。但是,这些默认设置会阻止我们对单节点群集执行任何有用的操作。为避免此问题,仅当 number_of_replicas 大于 1 时才强制要求仲裁。
移除 consistency 这个参数之后,用 wait_for_active_shards 这个参数替代了。
原因就是,consistency 检查是在 Put 之前做的。然而,虽然检查的时候,shard 满足 quorum,但是真正从 primary shard 写到 replica 之前,仍会出现 shard 挂掉,但 Update Api 会返回 succeed。因此,这个检查并不能保证 replica 成功写入,甚至这个 primary shard 是否能成功写入也未必能保证。
为了提高对系统写入的弹性,使用 wait_for_active_shards,可以将索引操作配置为在继续操作之前等待一定数量的活动分片副本。如果必需数量的活动分片副本不可用,则写入操作必须等待并重试,直到必需的分片副本已启动或发生超时。默认情况下,写入操作仅等待主分片在继续(即 wait_for_active_shards=1)之前处于活动状态。
注意,此设置大大降低了写入操作不写入所需数量的分片副本的可能性,但它并未完全消除这种可能性,因为此检查在写入操作开始之前发生。一旦写入操作正在进行,复制在任何数量的分片副本上仍然可能失败,但仍然可以在主分片上成功。在_shards 写操作的响应部分揭示了其复制成功 / 失败碎片的份数。
PUT /test_index/_doc/20?wait_for_active_shards=1
{"test_field":"test consistency"}
{
"_index" : "test_index",
"_type" : "_doc",
"_id" : "20",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 10,
"_primary_term" : 2
}
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
}