ES分布式写入的数据一致性问题

ES数据写入过程

ES索引由多个分片组成,分片有主分片和副本分片,且主分片和副本不能同时在同一节点上。可以看到,ES数据写入是一个分布式的过程。假设客户端发送批量写请求,ES写入过程如下:

1)协调节点接收到写请求,并做参数校验处理、生成id等;

2)计算每条数据归属的主分片,形成Map<ShardId, List<RequestBulkItem>>列表;

3)根据上面的列表,协调节点异步并行转发到所属分片;

4)主分片接收到协调节点转发过来的请求,先由lucene写入pageCache,然后记录事务日志;

5)主分片写入成功,转发写入请求到它的副本分片,副本分片执行过程同步骤4;

6)主分片收集所有副本分片是否写入成功,写入成功则返回给协调节点本分片写入成功;

7)协调节点接收所有主分片返回的写入状态,如果所有主分片写入成功,则任务本次写入过程完成;

8)返回成功给客户端;

ES分布式写入过程如图:

 

上面的流程,所有分片写入成功,则客户端写请求成功,数据是强一致的。但是如果有一些异常的场景下,比如主分片异常、副本分片异常,数据的一致性是怎样的呢?

一次写入的数据一致性

分片上写入失败有几种情况

1)主分片写入失败

1.1 lucene写入时发现数据格式错误;

1.2 IO异常等导致写入失败;

2)主分片不可用,有主分片处于UNASSIGNED或INITIALIZING状态;

3)副本写入失败

3.1)不可用,有副本处于UNASSIGNED或INITIALIZING状态;

3.2)IO异常等导致写入失败;

可以得出的是,主分片写入失败,整体的写请求应该是失败的。如果所有主分片写入都成功了,但是所有副本并没有同步成功,可以认为写请求是成功的吗?

ES认为是一次成功的请求。先看第一种情况,副本分片不可用。

ES写请求同步向副本同步前,会检查分片状态,会跳过处于UNASSIGNED或INITIALIZING状态的分片。这部分分片待Started前,会从主分片同步完整的数据;这样做是因为处于UNASSIGNED和INITIALIZING状态的分片不会对外提供查询服务,所以保证了对外的数据一致性。

再看第二种情况,IO异常等导致写入失败。

IO异常等导致副本写入失败,ES认为有必要关闭shard,并上报master重新分片副本shard。这种情况不需要等待重新分片的副本分片,主分片收到副本分片异常后,标记副本分片写入失败,并在副本分片恢复后继续同步。主分片将状态返回给协调节点,认为整体写入成功。

总结

1、如果索引分片都可用,并且写入主副本都成功了,才返回给客户端。在refresh后,主副本同时对外提供查询服务。这个同步时间很短,可以认为主副本的数据是一致的。如果副本同步时间较长,甚至超过1s,在同步的时间差内,可能造成数据不一致的情况,但是对外的数据最终是一致的,所以是分布式下的最终一致性。

2、如果索引主分片不可用,将禁止写入,数据是强一致的;

3、如果索引副本分片不可用,则有部分副本写入失败,整体写入认为成功。由于不可用的副本也不提供查询服务,所以对外数据仍然是一致的。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值