3.4 Elasticsearch的数据一致性
3.4.1 PacificA算法
Elasticsearch的数据存储模型基于的是主从模式,其具体实现中借鉴了微软的PacificA算法的一些思想理念。这里我们先简单介绍一下PacificA算法
1)特点
- 设计了一个通用和抽象的复制框架,模型容易验证正确性,实现不同的策略实例
- 配置管理和数据复制分离,Paxos负责管理配置,主副本策略负责数据复制
- 将错误检测和配置更新容在数据复制的交互里面,去中心化,降低瓶颈
2)专业术语
- Replica Group:互为副本的一组数据的集合,其中有一个primary,其余都是secondary
- Configuration: Repica Group的元数据,如副本有哪些,谁是primary等
- Configuration Manager: 配置一致性管理工具
- Serial Number(SN): 代表Update的执行顺序,每次update增加1
- Prepared List: Update操作的序列
- Committed List: 已经提交的update序列,是Prepared List的前缀
3)读写流程
写入流程
- 写请求进入主副本节点(简称主节点),该节点为它分配一个SN。使用SN创建一个
updateRequest
,然后将其插入prepareList
- 主节点将
updateRequest
发送给从副本节点(简称从副本)。从节点在接收到只有同样将其插入到自身的prepare list
之中,然后返回一个ack
给主节点 - 当主节点接收到所有从节点的ack之后,认为这条数据已经被所有从节点正确接收,此时可以进行提交,将此
UpdateRequest
放入committed list
,committed list
向前移动。 - 主节点告知客户端成功操作。对于每一个Prepare消息,主节点告知所有从节点自己
committed point
的位置。从节点在收到通知后移动自身committed point
到相同位置。
因为主节点只有在收到所有从节点ack之后才会提交数据到
committed list
,这样就保证了所有从节点中的数据始终是主节点数据的子集,从而保证了数据的一致性
读取流程
为了能够获取到最新的数据,所有读取操作只能在主节点中进行。如果应用可以容忍一定的读取窗口,也可以在从节点中进行
4)配置管理
全局的配置管理器负责管理所有副本组的设置。节点可以向管理器提出变更副本的请求,但必须附带上当前配置的版本号。只有当版本号与配置器版本号一致时,配置器才会响应变更请求
5)故障检测
pacificA通过租约机制来(lease)来进行主节点和从节点间的互相检测。主节点会定期向从节点获取租约,其可能产生以下情况
- 从节点没有及时(lease period)回复。主节点向配置管理器报告从节点异常,同时将自身降级
- 主节点没有及时(grace period)回复。从节点向配置管理器报告主节点异常,同时提升自己为新的主节点。当有多个从节点同时发现主节点异常时,按照先来后到的顺序提升
通过简单分析可知,当grace period > lease period时,就不会出现二主的问题
当发生网络分区时,由于grace period > lease period,那么主必然先探测到从下线,于是自身降级。而从探测到主下线之后提升自己为主。由于这时主已经下线,所以不存在二主的情况
6)ES中的PacificA
- master类似于配置管理器,负责维护索引信息
- SequenceNumber和Checkpoint类似PacificA算法中的Serial Number和Committed Point
- 集群状态中的routing_table存储了所有索引、索引有哪些shard、各自的主分片,以及位于哪个节点等信息,类似副本组
3.4.2 Elasticsearch中的分片如何工作
ES会把索引拆分成多个主分片来进行存储,同时,这些主分片都有多个副本。这些副本就是replication group(副本组)。这种数据副本模型属于主备模式,主分片是所有索引操作的入口。它负责检查操作是否有效,一旦主分片接收操作,其副本也要接收相应的操作
1)写入
概述
每个索引操作首先会解析到相应的副本组中,然后内部路由到相应的主分片上,主分片负责验证操作并转发请求到副本上。
ES在运行时,master会维护一个同步副本列表(in-sync copies),该列表包含了所有可用的副本和主分片信息,其中的副本都可以保证完成所有的索引处理操作,并给用户返回ack。主分片负责维护数据的一致性,因此必须将操作同步给在列表中的全部副本
流程图

异常处理
-
主分片写入失败
- 主分片节点通知master给自己降级,重新选一个主分片
-
副本写入失败
- 主分片通知master,将该副本从同步副本列表中移除,同时master会在其余节点重建该副本
-
主分片网络隔离
- 副本会拒绝来自过时主分片的操作。主分片访问master来获取最新的状态
-
没有任何副本
- 可以成功写入,但是数据安全无法保证。也可以设置
wait_for_active_shards
来保证数据安全性
- 可以成功写入,但是数据安全无法保证。也可以设置
2)读取
概述
主从模式下的一个好处就是所有主分片和副本的数据都是一致的(正在同步的除外)。因此主分片和同步副本列表中的副本均可以提供读取服务,这么做可以极大的提供吞吐量,提供优秀的并发性能。所以读取操作可以在同步副本列表(in-sync copies)中的任意分片上进行
流程图

注意
- 对于部分请求(如_search),ES倾向于及时返回结果,即使这个结果不是完整的
- 在正常情况下,读操作只在相关分片中执行一次,除非当读取有错误发生
- 对于在写操作响应前的读操作,有一定可能获取到还未写成功的数据。(因为写操作需要全部分片确认,而只要有一个分片写完,那么就有可能读取到这个数据)