elasticsearch读写文档--写模型

本文档基于es7.1版本。较新或交旧的版本可能在个别地方有出入。
es中的每一个index,都被切分成多个shards存储,这每一个shard称之为primary shard,并且每一个shard可能没有,或者有一个或多个copy,这些个copy称之为replicate。primary shard与其对应的replicate一起合称为replication group。replication group内部必须保证同步,也既各个shard内容一致。否则在读数据的时候,从不同的shard会获得不同的内容,这是任何一个系统都不能容忍的。keep sync的过程称之为data replication model。es使用primary-backup的复制模型,关于这个模型的详细介绍,可以参考微软的一篇论文Pacifica paper。这个我们后面再说。下面先来看看es写模型的简图:

elasticsearch读写文档--写模型

上面这个是正常流程下,es的写流程,首先

1,客户端向es集群中某个节点发送一个index document的请求,这个请求可能是CUD中的任一种。

2,接收到这个请求的节点作为coordinator,根据请求文档的_id或者routing值以及其他设置,计算对应的shard号,这个过程会得到一个replication group。因为任何的写操作必须在primary shard上进行,所以还要得到primary shard所在的节点。

3,然后coordinator会将请求转发给对应的primary shard处理。
4,primary shard接收到请求后,会验证变更内容的有效性,例如字段类型,长度等。

5,验证成功后,会向集群的master节点请求当前active的replicate的集合,称为in-sync set。

6.

7,每个索引会有一个index.write.wait_for_active_shards的参数。表示primary在处理更新请求之前,需要确保有对应数量的replicate处于active状态,一定程度上可以确保更新在适当数量上replicate copy成功应用。如果此时active的replicate copy数量小于设置值,则请求会一直等待,直到超时。也就是说这个更新请求不会得到处理。

8,

9,primary shard在本节点上处理更新,更新的过程大致为按照内容索引(生成)新记录,增加version,seq_no,并标记旧的记录为delete的,等待后台merge进程清理。如果请求携带了refresh参数的话,也会立即进行。默认情况下,refresh过程每隔index.refresh_interval时间进行一次,refresh后,在此之前更新的记录可以被读请求获取。这里也会涉及到translog、segment、commit等一系列概念,留在后面单独说明。

10,primary处理完成后,会将更新parallell发送到各个replicate copy进行。

11,in-sync set中可能全部成功,也可能有个别replicate copy失败。

12,primary需要把失败的copy通知到master,由master将这些copy从in-sync set中除去。同时,如果集群中有其他多余的node,master可能会在后台挑选一个node,迁移copy到其上。

13,master响应已从in-sync中除去失败的copy。

14,更新请求处理完成,primary shard返回成功到coordinator节点。

15,coordinator返回成功到客户端。

16,如果集群中有其他多余的node,master可能会在后台挑选一个node,迁移copy到其上。

以上,是正常流程下的写模型。

下面来看看异常情况:,

异常1:
elasticsearch读写文档--写模型

这里的异常从第11步开始,当前处理请求的primary shard因为网络分区,或其他原因造成primary 无法连接到集群中其他replicate copy或者master节点,此时集群已从in-sync set中promote了新的primary shard。promote的过程后面单独开篇。因为新的primary shard已在集群内取得一致,所以in_sync set中的replicate copy   拒绝reject了当前old primary shard的同步请求。然后old primary shard通过master得知新的primary shard(到master的网络通),将请求转发到新的primary shard上重新进行之前的步骤。或者old primary停止处理更新请求(到master的网络不通)。

这个异常会导致dirty  read的并发读问题,读者可思考一下。

还有另外一种异常,异常2:

elasticsearch读写文档--写模型

这里,在第9步的时候,primary shard因为自身的原因处理失败,例如资源异常等,会主动通知master,由masterpromote新的primary shard出来接收请求继续处理。在这个过程中,请求会等待默认1分钟。

 

大家可以想一想,如果只有一个primary shard,没有replicate  copy的情况下是怎样的。

总结,由上面两个处理模型可以看出来,es并不是十分的健壮,会出现只写一个shard的情况,以及幻读问题。同时,客户端的写请求需要等待in-sync  set中的replicate  copy处理完成,降低了写性能。并且,存在木桶效应,整个系统的replication group的写性能由最慢的那个shard决定。