为什么 Elasticsearch 允许我在不满足仲裁要求的单节点集群中索引文档?

Why does Elasticsearch allow me to index documents in a single node cluster that fails to meet quorum requirements?

来自https://www.elastic.co/guide/en/elasticsearch/guide/2.x/distrib-write.html

Note that the number_of_replicas is the number of replicas specified in the index settings, not the number of replicas that are currently active. If you have specified that an index should have three replicas, a quorum would be as follows:

int( (primary + 3 replicas) / 2 ) + 1 = 3

But if you start only two nodes, there will be insufficient active shard copies to satisfy the quorum, and you will be unable to index or delete any documents.

我 运行 在单节点集群上执行了以下命令,我能够成功地索引文档,即使上面的数学表明我不应该能够索引文档。

curl -X DELETE http://localhost:9200/a/?pretty
curl -X PUT -siH 'Content-Type: application/json' \
     http://localhost:9200/a?pretty -d '{

    "settings": {
        "number_of_replicas": 3
    }
}'
curl -sH 'Content-Type: application/json' -X PUT http://localhost:9200/a/a/1?pretty -d '{"a": "a"}'
curl -si http://localhost:9200/_cluster/health?pretty
curl -si http://localhost:9200/a/a/1?pretty

这是输出:

$ curl -X PUT -siH 'Content-Type: application/json' \
     http://localhost:9200/a?pretty -d '{

    "settings": {
        "number_of_replicas": 3
    }
}'
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-length: 77

{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "a"
}

$ curl -sH 'Content-Type: application/json' -X PUT http://localhost:9200/a/a/1?pretty -d '{"a": "a"}'
{
  "_index" : "a",
  "_type" : "a",
  "_id" : "1",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 4,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}

$ curl -si http://localhost:9200/_cluster/health?pretty
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-length: 468

{
  "cluster_name" : "docker-cluster",
  "status" : "yellow",
  "timed_out" : false,
  "number_of_nodes" : 1,
  "number_of_data_nodes" : 1,
  "active_primary_shards" : 5,
  "active_shards" : 5,
  "relocating_shards" : 0,
  "initializing_shards" : 0,
  "unassigned_shards" : 15,
  "delayed_unassigned_shards" : 0,
  "number_of_pending_tasks" : 0,
  "number_of_in_flight_fetch" : 0,
  "task_max_waiting_in_queue_millis" : 0,
  "active_shards_percent_as_number" : 25.0
}

$ curl -si http://localhost:9200/a/a/1?pretty
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-length: 124

{
  "_index" : "a",
  "_type" : "a",
  "_id" : "1",
  "_version" : 1,
  "found" : true,
  "_source" : {
    "a" : "a"
  }
}

即使我已将索引配置为具有 3 个副本分片并且数学表明我必须至少具有 3 个节点,我如何能够仅使用 1 个节点索引文档?

这是 ES 2.x 中的旧法定人数规则。从 ES 5.x 开始,写入一致性检查发生了一些变化,一个黄色的集群,即一个集群将分配所有主分片,将通过写入操作的一致性检查,并允许您索引和删除文档。

现在决定是否可以写入的方法是在索引操作中使用wait_for_active_shards参数。默认情况下,如果所有主分片都已启动,则将允许索引操作。您可以通过指定您希望在授权索引操作之前激活的分片数量来覆盖该设置,例如wait_for_active_shards=all 在您的情况下相当于 wait_for_active_shards=4 (4 = 1 主 + 3 副本)。如果您想要与之前相同的仲裁规则,请指定 wait_for_active_shards=3.

可以在 official documentation and here

中找到更多信息