简单说就是primary shard写完,会同步到replica shard上,两者最终可能会出现不一致的情况。那es是如何确定主副分片的写一致性的呢?
1、es5.0前,采用写入前检查存活shard的方式
(1)consistency
我们在发送任何一个增删改请求的时候,比如说put /product/book/id,都可以带上一个consistency参数,指明我们想要的写一致性类型
put /product/book/1?consistency=quorum
consistency有三个可选值:
one:只要有1个primary shard是可用的,就可以进行写操作
all:必须所有的primary shard和replica shard都是可用的,才可以进行写操作
quorum:默认值。要求所有的shard中,必须大部分shard都是可用的,才可以进行写操作
(2)quorum机制
写之前必须确保大多数shard都是可用的,具体会根据公式来判断是否可用
公式:可用的shard>=(primary shard数量+replica shard份数)/2+1时可以写入,举个例子
有3个primary shard,replica shard份数为1,总共有3+3*1=6个shard
quorum=(3+1)/2+1=3
所以,要求6个shard中至少有3个shard是可用的,才可以执行这个写操作
有种特殊情况,比如es只有1个节点,index有1个primary shard和1个replica shard,这种情况replica shard实际上是无法分配到节点上的,存活shard只有1个,而quorum=(1+1)/2+1=2,按公式算的话最终会无法写入,不过es对这种情况做了例外处理是可以正常写入的。
(3)quorum不齐全时不会直接拒绝写入
当quorum不齐全时,会默认等待1分钟,看等待期间可用的shard有没有增加到quorum的数量,等待时间结束若还不满足,则拒绝写入,比如我在写入时手动指定30秒等待(超时)时间,语法为
put /product/book/1?timeout=30
2、es5.0后,采用写入后才确认的方式
consistency检查是在put之前做的。然而虽然检查的时候,可用shard数量满足quorum数量,但是真正从primary shard写到replica shard之前,仍然会出现shard挂掉的可能,但update api会返回succeed。因此,这个检查并不能保证replica shard成功写入,甚至这个primary shard是否能成功写入也未必能保证。
因此es5.0后修改了语法,用wait_for_active_shards代替原来的consistency
#写入完1个primary shard就返回客户端
PUT /product/book/1?wait_for_active_shards=1
也可以在建索引的时候指定write.wait_for_active_shards
PUT /product
{ "mappings": {
"properties": {
"text": {
"type": "text",
"store" : true
},
"fullname": {
"type": "text"
}
}
},
"settings" : {
"index" : {
"number_of_shards" : 1,
"number_of_replicas" : 2,
"write.wait_for_active_shards":3
}
}
}