分布式系统中有一个重要理论:CAP。
- Consistency 数据一致性
分布式系统中,数据会存在多个副本中,有一些问题会导致写入数据时,一部分副本成功、一部分副本失败,造成数据不一致。
满足一致性就要求对数据的更新操作成功后,多副本的数据必须保持一致。
- Availability 可用性
在任何时候客户端对集群进行读写操作时,请求能够正常响应。
- Partition Tolerance 分区容忍性
发生通信故障时,集群被分割为多个无法通信的分区时,集群仍然可用。
apache zookeeper 保证了强 CP ,所以在可用性方面(A),需要保证超过半数的zookeeper服务正常(容灾),zookeeper集群有三种角色:leader,follower,observer ,当leader 节点宕机,follower节点会重新选举leader,在这期间,集群不可用,时间长达30S-120S。
Leader角色
Leader服务器是整个zookeeper集群的核心,主要的工作 任务有两项 1. 事物请求的唯一调度和处理者,保证集群事物处理的顺 序性 2. 集群内部各服务器的调度者
Follower角色
Follower角色的主要职责是 1. 处理客户端非事物请求、转发事物请求给leader服务器 2. 参与事物请求 Proposal 的投票(需要半数以上服务器 通过才能通知leader commit数据; Leader发起的提案, 要求Follower投票) 3. 参与Leader选举的投票
Observer角色
Observer 是 zookeeper3.3 开始引入的一个全新的服务器 角色,从字面来理解,该角色充当了观察者的角色。 观察zookeeper集群中的最新状态变化并将这些状态变化 同步到 observer 服务器上。Observer 的工作原理与 follower 角色基本一致,而它和 follower 角色唯一的不同 在于 observer 不参与任何形式的投票,包括事物请求 Proposal的投票和leader选举的投票。简单来说,observer 服务器只提供非事物请求服务,通常在于不影响集群事物 处理能力的前提下提升集群非事物处理的能力
而eureka集群中只要有一台存在就能保证注册中心的可用,eureka客户端在注册服务时发现连接不可用时会自动切换到其他节点,
除此之外,Eureka还有一种自我保护机制,如果再15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:
1、Eureka不再从注册列表中移除因为长时间没有收到心跳而应该过期的服务
2、Eureka任然能够提供服务注册和查询请求,但是占时不会将注册的服务同步到其他节点上(即保证当前节点依然可用)
3、当网络稳定时,当前实例新的注册信息才会被同步到其它节点上
eureka在保证高可用(A)的同时,失去了强数据一致性(C)
eureka的数据同步方式:Peer to Peer 模式,副本间不分主从,任何副本都可以接收写操作,然后每个副本间互相进行数据更新。对等复制模式,任何副本都可以接收写请求,不存在写压力瓶颈,但各个副本间数据同步时可能产生数据冲突。
Eureka Server 每当自己的信息变更后,例如 Client 向自己发起注册、续约、注销请求, 就会把自己的最新信息通知给其他 Eureka Server,保持数据同步。
如果自己的信息变更是另一个Eureka Server同步过来的,这是再同步回去的话就出现数据同步死循环了。
Eureka Server 在执行复制操作的时候,使用 HEADER_REPLICATION
这个 http header 来区分普通应用实例的正常请求,说明这是一个复制请求,这样其他 peer 节点收到请求时,就不会再对其进行复制操作,从而避免死循环。
还有一个问题,就是数据冲突,比如 server A 向 server B 发起同步请求,如果 A 的数据比 B 的还旧,B 不可能接受 A 的数据,那么 B 是如何知道 A 的数据是旧的呢?这时 A 又应该怎么办呢?
数据的新旧一般是通过版本号来定义的,Eureka 是通过 lastDirtyTimestamp
这个类似版本号的属性来实现的
还有一个重要的机制:hearbeat 心跳,即续约操作,来进行数据的最终修复,因为节点间的复制可能会出错,通过心跳就可以发现错误,进行弥补。