一、写一致性
ES写入流程为先写入Primary,再并发写入Replica,最后应答客户端
- 检查Active的Shard数
- 写入Primary
- 并发的向所有Replicate发起写入请求
- 等所有Replicate返回或者失败后,返回给Client
早期的ES版本中允许主从副本间进行异步复制,将Relica设置成replication=async(异步),这样Client就不需要等待ES副本是否写入成功的应答,但是这样丢数据的风险很大,后续版本已经移除,只能设置为replication=sync(同步),当在主分片和副本分片的写操作都完成后,写操作才返回
为了解决同步复制带来的性能问题,ES提供如下两个参数:
1. consistency参数
请求:
put /index/type/id?consistency=quorum
-
one:要求我们这个写操作,只要有一个primary shard是active活跃可用的,就可以执行
-
all:要求我们这个写操作,必须所有的primary shard和replica shard都是活跃的,才可以执行这个写操作
-
quorum:默认的值,要求所有的shard中,必须是大部分的shard都是活跃的,可用的,才可以执行这个写操作
quorum机制
计算活跃shard参数公式:
number_of_replicas>1时才生效
公式: quroum = int( (primary + number_of_replicas) / 2 ) + 1
4个primary shard,number_of_replicas=2,总共有4 + 4 * 2 = 12 个shard,quorum = int( (4 + 2) / 2 ) + 1 = 4,所以,要求12个shard中至少有4个shard是active状态的,才可以执行这个写操作
如果节点数少于quorum数量,可能导致quorum不齐全,进而导致无法执行任何写操作
2. timeout 参数
PUT /index/type/id?timeout=30s
quorum不齐全时,会wait(等待),默认1分钟,可以设置timeout手动去调,默认单位毫秒,等待期间,期望活跃的shard数量可以增加,最后不满足会报错
二、读一致性
对于读操作,新文档需要在所有副本分片写入后才能用于搜索,否则可能读到旧值
如果业务上要求立即读到最新数据,可以使用下面方法:
为搜索请求设置 ‘_preference’ 参数为 primary ,这样搜索请求会查询主分片,从而保证结果中的文档是最新版本
三、某个Replica持续写失败怎么办
假如一个Replica持续写入失败,那么这个Replica上的数据可能落后Primary很多,如果读请求路由到该Replica,读到的都是旧数据
解决方案:
一个Replica写失败了,Primary会将这个信息报告给Master,然后Master会在Meta中更新这个Index的InSyncAllocations配置,将这个Replica从中移除,移除后它就不再承担读请求