新建、索引和删除文档
新建、索引和删除请求都是写(write) 操作,它们必须在主分片上成功完成才能复制到相关的复制分片上。
下面我们罗列在主分片和复制分片上成功新建、索引或删除一个文档必要的顺序步骤:
- 客户端给
Node 1
发送新建、索引或删除请求。 - 节点使用文档的
_id
确定文档属于分片0
。它转发请求到Node 3
,分片0
位于这个节点上。 Node 3
在主分片上执行请求,如果成功,它转发请求到相应的位于Node 1
和Node 2
的复制节点上。当所有的复制节点报告成功,Node 3
报告成功到请求的节点,请求的节点再报告给客户端。
客户端接收到成功响应的时候,文档的修改已经被应用于主分片和所有的复制分片。你的修改生效了。
有很多可选的请求参数允许你更改这一过程。你可能想牺牲一些安全来提高性能。这一选项很少使用因为Elasticsearch已经足够快,不过为了内容的完整我们将做一些阐述。
replication
- 复制默认的值是
sync
。这将导致主分片得到复制分片的成功响应后才返回。 - 如果你设置
replication
为async
,请求在主分片上被执行后就会返回给客户端。它依旧会转发请求给复制节点,但你将不知道复制节点成功与否。 - 上面的这个选项不建议使用。默认的
sync
复制允许Elasticsearch强制反馈传输。async
复制可能会因为在不等待其它分片就绪的情况下发送过多的请求而使Elasticsearch过载。
consistency
- 默认主分片在尝试写入时需要规定数量(quorum) 或过半的分片(可以是主节点或复制节点)可用。这是防止数据被写入到错的网络分区。规定的数量计算公式如下:
int( (primary + number_of_replicas) / 2 ) + 1
consistency
允许的值为one
(只有一个主分片),all
(所有主分片和复制分片)或者默认的quorum
或过半分片。- 注意
number_of_replicas
是在索引中的的设置,用来定义复制分片的数量,而不是现在活动的复制节点的数量。如果你定义了索引有3个复制节点,那规定数量是:int( (primary + 3 replicas) / 2 ) + 1 = 3
- 但如果你只有2个节点,那你的活动分片不够规定数量,也就不能索引或删除任何文档。
timeout
- 当分片副本不足时会怎样?Elasticsearch会等待更多的分片出现。默认等待一分钟。如果需要,你可以设置
timeout
参数让它终止的更早:100
表示100毫秒,30s
表示30秒。 - 注意:新索引默认有
1
个复制分片,这意味着为了满足quorum
的要求需要 两个活动的分片。当然,这个默认设置将阻止我们在单一节点集群中进行操作。为了避开这个问题,规定数量只有在number_of_replicas
大于一时才生效。
检索文档
文档能够从主分片或任意一个复制分片被检索。
下面我们罗列在主分片或复制分片上检索一个文档必要的顺序步骤:
- 客户端给
Node 1
发送get请求。 - 节点使用文档的
_id
确定文档属于分片0
。分片0
对应的复制分片在三个节点上都有。此时,它转发请求到Node 2
。 Node 2
返回文档(document)给Node 1
然后返回给客户端。
对于读请求,为了平衡负载,请求节点会为每个请求选择不同的分片——它会循环所有分片副本。
可能的情况是,一个被索引的文档已经存在于主分片上却还没来得及同步到复制分片上。这时复制分片会报告文档未找到,主分片会成功返回文档。一旦索引请求成功返回给用户,文档则在主分片和复制分片都是可用的。
局部更新文档
update
API 结合了之前提到的读和写的模式。
下面我们罗列执行局部更新必要的顺序步骤:
- 客户端给
Node 1
发送更新请求。 - 它转发请求到主分片所在节点
Node 3
。 Node 3
从主分片检索出文档,修改_source
字段的JSON,然后在主分片上重建索引。如果有其他进程修改了文档,它以retry_on_conflict
设置的次数重复步骤3,都未成功则放弃。- 如果
Node 3
成功更新文档,它同时转发文档的新版本到Node 1
和Node 2
上的复制节点以重建索引。当所有复制节点报告成功,Node 3
返回成功给请求节点,然后返回给客户端。
update
API还接受《新建、索引和删除》章节提到的routing
、replication
、consistency
和timout
参数。
基于文档的复制
当主分片转发更改给复制分片时,并不是转发更新请求,而是转发整个文档的新版本。记住这些修改转发到复制节点是异步的,它们并不能保证到达的顺序与发送相同。如果Elasticsearch转发的仅仅是修改请求,修改的顺序可能是错误的,那得到的就是个损坏的文档。