参考:Zookeeper入门
rpc使用zk的例子1
rpc使用zk的例子2
添加链接描述
添加链接描述
添加链接描述
添加链接描述
添加链接描述
添加链接描述
添加链接描述
文章目录
Zookeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。
Zookeeper 功能较多,能够配置维护、域名服务、分布式同步、组服务等,也有很多服务框架使用 Zookeeper 来做注册中心。
1.命名服务 2.配置管理 3.集群管理 4.分布式锁 5.队列管理
zookeeper注册中心(zookeeper的通知机制)
Zookeeper 用来做服务注册中心,主要是因为它具有节点变更通知功能
,只要客户端监听相关服务节点,服务节点的所有变更,都能及时的通知到监听客户端,这样作为调用方只要使用 Zookeeper 的客户端就能实现服务节点的订阅和变更通知功能了,非常方便。
另外,Zookeeper 可用性还算是可以的,因为只要半数以上的选举节点存活,整个集群就是可用的。
zookeeper注册中心的实现机制
在zookeeper中进行服务注册就是在zookeeper创建了一个节点,结点存储该服务的IP端口号,调用方式(协议,序列化)等,由服务提供者去创建,以供消费者去获取信息,服务端启动服务时,会将服务名称,IP地址等信息注册到注册中心,服务消费者在第一次调用服务时,会通过注册中心找到相应的服务的IP地址列表,并缓存到本地
,以供后续使用。
当消费者调用服务时,不会再去请求注册中心,而是直接通过负载均衡算法从IP列表中取一个服务提供者的服务器调用服务。当服务提供者的某台服务器宕机或下线时,相应的ip会从服务提供者IP列表中移除。同时,注册中心会将新的服务IP地址列表发送给服务消费者机器,缓存在消费者本机。
zookeeper提供心跳检测,会盯上想服务端发送一个请求(实际上建立的是一个 socket 长连接),如果长期没有响应,服务中心就认为该服务提供者已经“挂了”,并将其剔除)
服务消费者会去监听相应路径(/HelloWorldService/1.0.0),一旦路径上的数据有任务变化(增加或减少),zookeeper都会通知服务消费方服务提供者地址列表已经发生改变,从而进行更新。
zookeeper 与生俱来的容错容灾能力(比如leader选举),可以确保服务注册表的高可用性。
使用 zookeeper 作为注册中心时,客户端订阅服务时会向 zookeeper
注册自身;主要是方便对调用方进行统计、管理。但订阅时是否注册 client 不是必要行为,和不同的注册中心实现有关,例如使用 consul
时便没有注册。
Zookeeper工作原理 (zookeeper的核心:原子广播
Zookeeper的底层选举原理?如何保持zookeeper数据一致性?Zab原子广播协议
Zookeeper 的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议
。
Zab协议有两种模式,它们分别是恢复模式(选主)和广播模式(同步)
。
当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和 leader的状态同步以后,恢复模式就结束了。
状态同步保证了leader和Server具有相同的系统状态。
为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务
。
所有的提议(proposal)
都在被提出的时候加上了zxid。
实现中zxid是一个64位的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch,标识当前属于那个leader的统治时期。低32位用于递增计数。
zxid什么情况下会不一致?
在同步的时候一台突然宕机了
zab原子广播协议有两种模式
1、恢复模式:初次启动节点时,选举leader,从节点进入恢复模式同步主节点数据
2、广播模式:解决每个节点的数据同步问题
恢复模式
当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数server完成了和leader的状态同步以后,恢复模式就结束了。
状态同步保证了leader和server具有相同的系统状态。
广播模式
一旦Leader已经和多数的Follower进行了状态同步后,他就可以开始广播消息了,即进入广播状态。
这时候当一个Server加入ZooKeeper服务中,它会在恢复模式下启动,发现Leader,并和Leader进行状态同步
。待到同步结束,它也参与消息广播。
ZooKeeper服务一直维持在Broadcast状态,直到Leader崩溃了或者Leader失去了大部分的Followers支持。
Broadcast模式极其类似于分布式事务中的2pc(two-phrase commit 两阶段提交):即Leader提起一个决议,由Followers进行投票,Leader对投票结果进行计算决定是否通过该决议,如果通过执行该决议(事务),否则什么也不做。
对于客户端发送的写请求,全部由 Leader 接收,Leader 将请求封装成一个事务 Proposal,将其发送给所有 Follwer ,然后,根据所有 Follwer 的反馈,如果超过半数成功响应,则执行 commit 操作(先提交自己,再发送 commit 给所有 Follwer)。
当超过半数成功回应,则执行 commit ,同时提交自己。同时每个事物都有一个zxid 还有一个消息队列 解决异步,同时,针对各个节点的数据不一致性问题还有选举过程。
zookeeper分布式锁(与Redis分布式锁)
zookeeper分布式锁
Zk实现分布式锁思想:节点保持唯一
、事件通知
、临时节点
(生命周期和session会话关联)
因为Zookeeper节点路径保持唯一,不允许重复 且有临时节点特性,连接关闭后当前节点会自动消失,从而实现分布式锁。
zk实现分布式锁的落地方案:
-
使用zk的临时节点和有序节点,
每个线程获取锁就是在zk创建一个临时有序的节点
,比如在/lock/目录下。 -
创建节点成功后,获取/lock目录下的所有临时节点,再判断当前线程创建的节点是否是所有的节点的序号最小的节点
-
如果当前线程创建的节点是所有节点序号最小的节点,则认为获取锁成功。
-
如果当前线程创建的节点不是所有节点序号最小的节点,则对节点序号的前一个节点添加一个事件监听。
-
比如当前线程获取到的节点序号为/lock/003,然后所有的节点列表为[/lock/001,/lock/002,/lock/003],则对/lock/002这个节点添加一个事件监听器。
-
如果锁释放了,会唤醒下一个序号的节点,然后重新执行第3步,判断是否自己的节点序号是最小。
-
-
Redis分布式锁
使用Redis做分布式锁的思路大概是这样的:在redis中设置一个值表示加了锁,然后释放锁的时候就把这个key删除。
除了要考虑客户端要怎么实现分布式锁之外,还需要考虑redis的部署问题。
redis有3种部署方式:
-
单机模式
-
master-slave + sentinel选举模式
-
redis cluster模式
使用redis做分布式锁的缺点在于:如果采用单机部署模式,会存在单点问题,只要redis故障了。加锁就不行了。
采用master-slave模式,加锁的时候只对一个节点加锁,即便通过sentinel做了高可用,但是如果master节点故障了,发生主从切换,此时就会有可能出现锁丢失的问题。
Redisson
实现Redis的分布式锁,除了自己基于redis client原生api来实现之外,还可以使用开源框架:Redission
Redisson是一个企业级的开源Redis Client,也提供了分布式锁的支持。我也非常推荐大家使用,为什么呢?
回想一下上面说的,如果自己写代码来通过redis设置一个值,是通过下面这个命令设置的。
SET anyLock unique_value NX PX 30000
这里设置的超时时间是30s,假如我超过30s都还没有完成业务逻辑的情况下,key会过期,其他线程有可能会获取到锁。
这样一来的话,第一个线程还没执行完业务逻辑,第二个线程进来了也会出现线程安全问题。所以我们还需要额外的去维护这个过期时间,太麻烦了~
我们来看看redisson是怎么实现的?先感受一下使用redission的爽:
Zookeeper与Redis实现分布式锁的区别?
CAP理论
CAP理论:对一个分布式系统中,当涉及读写操作时,只能保证一致性、可用性、分区容错性,三者中的两个,另外一个必须被牺牲。
- C(一致性)实际上保证的是对于一个客户端而言,每一次的读操作,返回的一定是最新的写操作的结果。
- A(可用性)是指非故障的节点在合理的时间内返回合理的响应,数据允许可以出错,允许脏读,数据同步的时候服务可用,数据最终会一致,注重服务可用。
- P(分区容错性)是指当出现网络分区后,系统能够继续“履行职责”,允许出现网络故障,不会因为网络故障判断一个节点宕机了。
现在的对于CAP的应用主要分为了AP、CP两种,因为对于分布式而言P(分区容错性)是必选的,如果我们选择CA(一致性、可用性)发生分区现象时,由于网络的不可靠性,为了保证一致性我们一定会在在分区时禁止写入,就与可用性有了冲突。
CP,即网络分区时为了保证一致性,在客户端访问到数据未同步到最新的节点时会返回error。也就是暂时放弃了可用性的要求。
AP,即网络分区出现时,在客户端访问到数据未同步到最新的节点时会返回旧的数据给他,暂时放弃了一致性的要求。在数据一致之后再用后续的方案进行数据筛选。
BASE是CAP理论中AP方案的延伸,指基本可用、软状态、最终一致性,核心思想是即使无法做到强一致性,但应用可以采用适合的方式达到最终一致性。
Paxos算法是基于消息传递且具有高度容错特性的一致性算法。目的是为了解决分布式环境下一致性的问题。
zookeeper采用CP
2PC两阶段提交协议解决分布式数据同步问题?(?
2PC两阶段提交协议应用于分布式事务场景,解决分布式多个系统间数据的一致性,如数据库XA机制。
多个服务器同时进行写操作,一台出错全部回滚。是全局的事务id
事务请求:只有在写操作的时候才会用到事务
Zk底层解决分布式事务问题,就是采用类似2pc两阶段提交协议的Zab协议;
集群管理
集群管理两点:1.是否有机器退出和加入 2.选举master。
对于第一点,所有机器约定在父目录GroupMembers下创建临时目录节点,然后监听父目录节点的子节点变化消息。
一旦有机器挂掉,该机器与 zookeeper的连接断开,其所创建的临时目录节点被删除,所有其他机器都收到通知:某个兄弟目录被删除,于是,所有人都知道:它上船了。
新机器加入也是类似,所有机器收到通知:新兄弟目录加入,highcount又有了,对于第二点,我们稍微改变一下,所有机器创建临时顺序编号目录节点,每次选取编号最小的机器作为master就好。
为什么Zookeeper集群节点一定要是奇数?为什么集群数量要大于三台?
- 因为节点剩余数要满足过半机制,剩余节点>总节点/2,三台集群和四台集群都只能宕机一台,还不如三台
- 偶数台容易造成票数相同
集群数量要大于三台的原因:
两台做集群的话,故障一台就不满足过半机制了,还不如不集群
Zookeeper中有哪三种类型的节点?分别是什么作用?
1.Leader类型 领导类型
负责写的请求,和各个节点同步;
2.Follower类型 跟随者
负责读的请求和投票决议
3.ObServer类型 观察者
和Follower大部分特征都是一样的,唯一区别就是不能参与选举和投票
注意:zk集群在后期扩容的时候,建议不要使用follow节点类型,会导致选举时间变长。
为什么要使用ObServer类型?
主要不影响原来本身选举的时间的效率、目的是提高客户端查询效率;
写操作都是转发给leader写的,读操作follower或者observer自己读
节点类型分为四种
1、临时节点–会话关闭,就自动消失(zk.close())
2、持久节点–永久持久化到硬盘
3、临时有序节点,自增
4、持久有序节点
Zookeeper选主流程(basic paxos)
系统默认的选举算法为fast paxos
。