首先引出本人对ElasticSearch分布式的特点;再者针对分布式系统CAP理论,来论证分析ElasticSearch如何实现分布式?另外分析ElasticSearch在CAP理论的实现中是如何在三取二中权衡的?最后回归到论点。
1.强一致性,ES保证每一次的数据的更新都更新都所有的节点。
2.高可用,ES保证在某些节点/分片挂掉后仍不影响对外的响应。
3.低分区容错性。
以上是个人对ElasticSearch的分布式方式的特点认知,非官方观点。有其他观点的同学可以留言讨论。
如果系统对一个写操作返回成功,那么之后的读请求都必须读到这个新数据;如果返回失败,那么所有读操作都不能读到这个数据,对调用者而言数据具有强一致性(strong consistency) (又叫原子性 atomic、线性一致性 linearizable consistency)
所有读写请求在一定时间内得到响应,可终止、不会一直等待
在网络分区的情况下,被分隔的节点仍能正常对外服务
CAP是一个理想的理论,现实应用中不会出现CAP三个特点都占齐的分布式系统。
CA without P
丢弃P:对于一个分布式系统,如果不能满足分区容错性,那么意味着集群的各个节点之间都保证相互之间的协调工作,
如果网络异常,那么和单个节点没有两样,也不能称之为分布式系统。因此分区容错性是必须要保证的。
CP without A
丢弃A:如果牺牲可用性,换来数据一致性。对于这种情况也有相应的应用场景,比如淘宝在双十一的高峰,
为了保证数据的一致性,在我们支付的时候,有时候会等待很久都不能支付成功。这是因为并发量太大,
必须要保证交易数据的一致性,即使要牺牲一点可用性。
AP wihtout C
丢弃C:如果牺牲一致性,换来可用性。对于这种情况,比较典型的就是火车订票系统,
我们常常会在抢票的时候发现系统显示还有剩余的票,但是当在下单付款的时候却已没有剩余的票。
这样虽然会降低用户的使用体验,但是也不至于大量用户请求阻塞服务器。
下面我将结合CAP理论讨论一下ElasticSearch如何满足上面三个特性的?
ES实现分布式是实现了一个集群系统,在这个系统中各个节点都可以接收请求消息和存储数据,并通过内部的一套路由算法实现各个节点协调一致地工作。在这个集群系统中,需要一个集群管理员来负责集群的所有管理工作,这个集群管理员称之为Master节点。Master节点的唯一性是ElasticSearch一致性的一个重要组成部分,Master节点的选举依赖与ElasticSearch内部一套独特的Master节点选举策略。下面简单分析一下:
1,首先简单介绍一下ElasticSearch的节点类型
ElasticSearch有四种节点类型,这里主要介绍两种:
另外两种节点不在此介绍,详情可见ES官方文档:ElasticSearch节点
2,ES节点发现:ZenDiscovery‘
实现机制核心的点:广播
Node启动后,首先要通过yml配置文件中配置的discovery.zen.ping.unicast.hosts的值去发送广播到每一个节点,各个节点接收到消息后发起响应,集群的Master节点(有就用当前Master节点,无就选举)加入集群。
ZenDiscovery是ES自己实现的一套用于节点发现和选主等功能的模块,没有依赖Zookeeper等工具。
3,Master节点选举
当集群启动后,每一个Master-eligible node都会每隔一定时间去ping集群的各个节点确定集群的Master是否存活。如果集群刚启动没有Master节点或者Master节点由于网络原因或者负载较大没有及时响应,此时Master-eligible node就会发起一次选举,并让集群中的节点给自己投票。当该节点收到的票数大于等于(Nodes/2+1)个票数时(即超过半数),该节点选举为Master节点。
为了保证选举的一致性,ElasticSearch还有另外一套机制-选举周期。即在一个选举周期内的票数在有效,否则的话清空选票重新选举。
4,集群扩缩容
当集群建立后,集群节点的加入或离开保证集群平衡也是ElasticSearch一致性的一个重要组成部分。
split brain脑裂问题
脑裂是指在同一个ES集群中出现两个Master节点。
可能出现的原因:
1.网络问题:集群间的网络延迟导致一些节点访问不到master,认为master挂掉了从而选举出新的master,
并对master上的分片和副本标红,分配新的主分片
2.节点负载:主节点的角色既为master又为data,访问量较大时可能会导致ES停止响应造成大面积延迟,
此时其他节点得不到主节点的响应认为主节点挂掉了,会重新选取主节点。
3.内存回收:data节点上的ES进程占用的内存较大,引发JVM的大规模内存回收,造成ES进程失去响应。
脑裂问题解决方案:
1.减少误判:discovery.zen.ping_timeout节点状态的响应时间,默认为3s,可以适当调大,
如果master在该响应时间的范围内没有做出响应应答,判断该节点已经挂掉了。调大参数。
2.选举触发 discovery.zen.minimum_master_nodes:1
该参数是用于控制选举行为发生的最小集群主节点数量。
当备选主节点的个数大于等于该参数的值,且备选主节点中有该参数个节点认为主节点挂了,进行选举。
官方建议为(n/2)+1,n为主节点个数(即有资格成为主节点的节点个数)
增大该参数,当该值为2时,我们可以设置master的数量为3,这样,挂掉一台,其他两台都认为主节点挂掉了,
才进行主节点选举。
3.角色分离:即master节点与data节点分离,限制角色
主节点配置为:node.master: true node.data: false
从节点配置为:node.master: false node.data: true
ElasticSearch集群中Master节点为了协调一致地管理集群,保证所有节点的信息同步是一致性的必要条件。
ElasticSearch采用给所有节点发送ClusterState信息体,同步各个节点的信息,保证一致性。
1,什么是ClusterState
在ES中,Master节点是通过发布ClusterState来通知其他节点的。Master会将新的ClusterState发布给其他的所有节点,当节点收到新的ClusterState后,会把新的ClusterState发给相关的各个模块,各个模块根据新的ClusterState判断是否要做什么事情,比如创建Shard等。即这是一种通过Meta数据来驱动各个模块工作的方式。
集群中的每个节点都会在内存中维护一个当前的ClusterState,表示当前集群的各种状态。ClusterState中包含一个MetaData的结构,MetaData中存储的内容更符合meta的特征,而且需要持久化的信息都在MetaData中,此外的一些变量可以认为是一些临时状态,是集群运行中动态构建出来的。
2,什么是MetaMeta的组成?Meta的存储?Meta恢复?
Meta是用来描述数据的数据。在ES中,Index的mapping结构、配置、持久化状态等就属于meta数据,集群的一些配置信息也属于meta。这类meta数据非常重要,假如记录某个index的meta数据丢失了,那么集群就认为这个index不再存在了。ES中的meta数据只能由master进行更新,master相当于是集群的大脑。
ElasticSearch会把Meta和Data都写入到这个目录中,其中目录名为_state的代表该目录存储的是meta文件。
假设ES集群重启了,那么所有进程都没有了之前的Meta信息,需要有一个角色来恢复Meta,这个角色就是Master。所以ES集群需要先进行Master选举,选出Master后,才会进行故障恢复。
当Master选举出来后,Master进程还会等待一些条件,比如集群当前的节点数大于某个数目等,这是避免有些DataNode还没有连上来,造成不必要的数据恢复等。
当Master进程决定进行恢复Meta时,它会向集群中的MasterNode和DataNode请求其机器上的MetaData。对于集群的Meta,选择其中version最大的版本。对于每个Index的Meta,也选择其中最大的版本。然后将集群的Meta和每个Index的Meta再组合起来,构成当前的最新Meta。
3,ClusterState更新流程
ElasticSearch为了保证集群信息同步的一致性,采用两阶段提交的方式。当ElasticSearch向集群发送同步ClusterState的请求,所有的节点接收到信息后向发起者发起响应,如果超过半数则发起提交请求。
1,数据写入流程
ES写入流程为先写入Primary,再并发写入Replica,最后应答客户端,流程如下:
1,检查Active的Shard数。String activeShardCountFailure = checkActiveShardCount();
2,写入Primary。primaryResult = primary.perform(request);
3,并发的向所有Replicate发起写入请求 performOnReplicas(replicaRequest, globalCheckpoint, replicationGroup.getRoutingTable());
4,等所有Replicate返回或者失败后,返回给Client。
private void decPendingAndFinishIfNeeded() {
assert pendingActions.get() > 0 : "pending action count goes below 0 for request [" + request + "]";
if (pendingActions.decrementAndGet() == 0) {
finish();
}
}
2,PacificA算法
That model is based on having a single copy from the replication group that acts as the primary shard. The other copies are called replica shards. The primary serves as the main entry point for all indexing operations. It is in charge of validating them and making sure they are correct. Once an index operation has been accepted by the primary, the primary is also responsible for replicating the operation to the other copies.
该算法具有以下几个特点:
1、强一致性。
2、单Primary向多Secondary的数据同步模式。
3、使用额外的一致性组件维护Configuration。
4、少数派Replica可用时仍可写入。
副片:es为了更好地稳定性和容灾,除了进行必要的索引备份外,副本的添加可以更好地维持集群数据完整性。
当数据写入主分片后然后将数据同步到副本分片中,一旦系统中的主分片异常,则副本分片则可以很好地替补主分片保证数据的完整性。
分片的路由算法:shard = hash(routing) % number_of_primary_shards
缺点:写入延迟,效率低
优点:防止数据丢失,高可用
ElasticSearch是多节点集群系统,ElasticSearch中可以启动多个节点,各个分片均匀地分布在各个节点。并且ElasticSearch会将主分片和其副本分片分布在不同的节点上,一旦主分片所在节点挂掉了,则另一个节点的备份分片立即升级为主分片,保证系统的可用性。
有一些任务只能由主节点去处理,比如创建一个新的 索引或者在集群中移动分片。
由于一个集群中只能有一个主节点,所以只有这一节点可以处理集群级别的元数据变动。
大多数情况下,master可以处理,但当集群元数据改变的速度超过了master节点处理的速度时,
将会导致这些元数据操作的任务被缓存入队列中,即pending tasks。
pending task API 将会显示队列中被挂起的所有的集群元数据改变的任务。
高分区容忍性的定义是讲分布式系统中一旦发生网络分区或者某一些节点因为网络等原因无法连接到分布式系统中时,这些节点可以依旧对外提供完整独立的服务,也就是将每一个节点拥有的功能是完整的,节点与节点之间的耦合度较低,任意一个节点都可以对外提供完整的服务。
现在我们来观测ElasticSearch集群的特点,ElasticSearch集群各个节点各个节点是高度协调,高度耦合的。
原因如下:
1,各个节点地位平等,各个节点都用于存储数据,每个节点都接收请求数据,当发现数据不在本身节点时将请求路由到对应节点获取数据返回;各个节点是高度协调运作的。
2,ElasticSearch的主分片是均匀分布在各个节点上,可以假设这样一种场景:ELasticSearch中存在两个节点,建立一根索引index,2个主分片0个副本分片,现在两个主分片均匀地分布在两个节点上;当网络发生异常时,此时集群状态是RED状态,任意一个节点也无法对外提供服务,此时系统处于瘫痪状态。各个节点是高度耦合的。
综合上面两点,ElasticSearch是一个低分区容忍性的系统。
综上分析,ElasticSearch是一个高一致性,高可用,低分区容忍性的(CA)分布式系统。
此观点是个人观点,且观点不唯一,如果各位同学有什么其他更好的理解可以留言本人细致讨论,谢谢。
下面是一些国外众网友对ElasticSearch结合CAP理论的理解,大家有兴趣可以了解一下。
elasticsearch and the CAP theorem
【Elastic讨论区】elasticsearch and the CAP theorem
【Elastic讨论区】CAP theorem