Zookeeper、Nacos、Eureka的比较
CAP原则;
Consistency:数据一致性(主要在乎数据的安全和一致,用户体验放在第二)
Availability:可用性 (收到请求要进行反馈,用户体验第一)
Partition tolerance:分区容错性。 (遇到故障时,仍能够提供C/A的表现)
Eureka:
遵循AP原则,通过服务注册发现集群,来保证可用性,但不保证数据的强一致性。
通过心跳、保护模式、请求自动切换到存活的服务器等来保证分区容错性。
大体梳理一下Eureka集群的工作流程:
1.服务端:启动Eureka集群,集群之间通过Replicate来同步注册表,集群中每个集群都有自己的注册表信息。
90s内没有收到心跳就置为失效,如果大量失效的情况存在,Eureka判断是否是网络波动等问题,不再置为失效(保护模式开启)
客户端:
向注册中心注册服务,信息会被记录到某个注册中心的注册表。
定时的从注册中心获取服务注册表,同步到本地缓存。如果客户端微服务之间进行调用,先从本地缓存找,找不到去更新注册信息再同步到本地缓存。
程序关闭,向Server发取消请求,从该注册中心的注册表中删除。
Zookeeper:
遵循CP原则。数据一致性和分区容错性。
数据模型:
树结构和文件目录结构的混合
Zookeeper是读多写少的场景,存的信息也是状态和配置信息,每个节点的大小不超过1MB
ZNode每一个节点都有唯一路径
ZNode结构:
Data:存储数据信息
ACL:Znode访问权限
stat:各种元数据。事务ID、版本号、时间戳、大小等等。
child:指向子节点的引用
Znode节点的类型:
持久节点:一直存在,除非手动删除
持久顺序节点:加了顺序性。父节点会维护一个自增整性数字,用于子节点的创建的先后顺序。
临时节点:生命周期和客户端会话绑定,客户端失效,节点清除。只能作为叶子节点
临时顺序节点:添加了顺序性
Zookeeper的特性:
• 「顺序一致性」:从同一客户端发起的事务请求,最终将会严格地按照顺序被应用到 ZooKeeper 中去。
• 「原子性」:所有事务请求的处理结果在整个集群中所有机器上的应用情况是一致的,也就是说,要么整个集群中所有的机器都成功应用了某一个事务,要么都没有应用。
• 「单一视图」:无论客户端连到哪一个 ZooKeeper 服务器上,其看到的服务端数据模型都是一致的。
• 「可靠性:」 一旦服务端成功地应用了一个事务,并完成对客户端的响应,那么该事务所引起的服务端状态变更将会被一直保留下来。
「实时性(最终一致性):」 Zookeeper 仅仅能保证在一定的时间段内,客户端最终一定能够从服务端上读取到最新的数据状态。
Zookeeper的操作:
create:创建
delete:删除
exists:判断是否存在
getData:获得一个节点
setData:设置一个节点
getChildren:获取节点下所有子节点
Zookeeper客户端在请求读操作getData的时候,可以选择是否设置Watch。
1.客户端调用getData方法,watch参数是true。服务端接到请求,返回节点数据,并且在对应的哈希表里插入被Watch的Znode路径,以及Watcher列表。
2.当被Watch的Znode已删除,服务端会查找哈希表,找到该Znode对应的所有Watcher,异步通知客户端,并且删除哈希表中对应的Key-Value。
Zookeeper的一致性保证:
通过主从同步,更新数据首先更新到主节点,再同步到从节点。
读数据,读从节点数据
为了保持主从一致性,采用ZAB协议。
ZAB协议的三种节点状态:
looking:选举状态
following:follower节点状态(从节点)
leading:leader节点状态(主节点)
最大ZXID:节点本地的最新事务编号,包含epoch和计数两部分 zxid越大说明事务越新
如果zookeeper的主节点挂掉,会进行崩溃恢复操作:
1.Leader Election(根据zxid选举)
他们会向其他节点发起投票,投票包含自己的服务器id和ZXID(最新事务id)
接下来会比较自己和投票的节点的zxid,如果别人的大就重新投票,投票给目前已知最大的zxid
每次投票后,服务器统计投票数量,当某个节点有一半以上的票数,就会成为准leader,状态变为Leading
2.Discovery(发现,确保最新数据)
1.接受所有从节点发来的epoch,选出最大的并+1生成新的发给从节点
2.从节点接收到最新的epoch,返回ACL+最大zxid和历史事务日志给leader
3.leader选出最大的zxid,并更新自身历史日志
3.同步阶段
此时leader还是准leader,leader把收集到的最新的历史事务日志,同步给所有的从节点,半数以上同步成功,leader成为正式leader
ZAB协议怎么写入数据?
broadcast广播:
1.客户端发写数据请求给从节点
2.从节点吧写请求转发给主节点
3.Leader采用二阶段提交方式,先发送Propose广播给Follower。
4.Follower接到Propose消息,写入日志成功后,返回ACK消息给Leader。
5.Leader接到半数以上ACK消息,返回成功给客户端,并且广播Commit请求给Follower。
ZAB协议通过事务id和版本号,保证数据的更新和读取有序
zookeeper的应用场景:
1.利用zookeeper的临时顺序节点,可以轻松实现分布式锁
2.Dubbo框架的注册和发现,利用Znode和Watcher,可以实现分布式服务的注册和发现
3.共享配置和状态信息。
Redis的分布式解决方案Codis,就利用了Zookeeper来存放数据路由表和 codis-proxy 节点的元信息。同时 codis-config 发起的命令都会通过 ZooKeeper 同步到各个存活的 codis-proxy
命名服务: 根据指定名字获取资源,Zookeeper可以创建全局唯一路径,这个路径可以作为一个名字。
配置管理: 利用ZNode和watch来做发现注册
集群管理: Zookeeper对集群管理,选举机制等
分布式锁的实现原理:
• 获取锁过程 (创建临时节点,检查序号最小)
• 释放锁 (删除临时节点,监听通知)
zookeeper会为锁节点创建持久节点
客户端想获取锁,首先会在lock节点下创建顺序临时节点,这种节点的好处就是不用手动删除,redis如果清理不及时就很尴尬,zookeeper就没有这种问题
想获取锁的客户端会判断自己是不是序号最小的那个节点,如果是最小的获取锁。
如果不是需要最小的,给前一节点加watch监听,等前一节点用完释放了锁,就可以得到消息拿到锁了。