ZooKeeper集群搭建问题
单机zk会带来那些问题?
zk宕机后不会影响现有consumer和provider之间的调用,但是新的provider想要注册到注册中心上是不行的,因为zk已经宕机了。因此单点zk一旦宕机就会影响新的provider的注册和新的consumer去订阅可用列表。
因此我们需要将zk搭建成集群的,那么问题又来了,搭建集群时搭建几台呢?建议是搭建奇数台,最少搭建三台,搭建偶数可以吗?是可以的,但是在选举过程中没有太大用处,因为zk的leader也是遵从半数规则,使用公式计算半数(zk服务器的总数/2+1),3的半数是2,4的半数是3,因此3台和4台允许宕机的机器数都是1台,在选举中反而增加了网络通信负担。
1、server和myid要保持一致;
server.0=127.0.0.1:2888:3888 => 对应myid 为0
server.1=127.0.0.1:2889:3889 => 对应myid 为1
server.2=127.0.0.1:2890:3890 => 对应myid 为2
[myid:2] - ERROR [main:aaa@qq.com] - Unexpected exception, exiting abnormally
java.lang.RuntimeException: My id 3 not in the peer list
at org.apache.zookeeper.server.quorum.QuorumPeer.startLeaderElection(QuorumPeer.java:718)
at org.apache.zookeeper.server.quorum.QuorumPeer.start(QuorumPeer.java:637)
at org.apache.zookeeper.server.quorum.QuorumPeerMain.runFromConfig(QuorumPeerMain.java:170)
at org.apache.zookeeper.server.quorum.QuorumPeerMain.initializeAndRun(QuorumPeerMain.java:114)
at org.apache.zookeeper.server.quorum.QuorumPeerMain.main(QuorumPeerMain.java:81)
错误原因:根据报错日志,可以看出,是因为myid文件中配置有误。导致无法找到这个myid=3的peer。
2、选举过程
1、启动时选举:
现在有myid为0,1,2的机器,先后启动0,1机器,可以看到0机器打印日志:
1机器打印日志如下:
再启动2机器,打印日志如下:
2、Leader服务出现故障时选举
某一时刻,myid为1的机器出现故障,此时进行选举,myid为2的id成为leader
写请求(事务请求)
会转发给Leader(改进版2pc,过半同意即可)
1.事务请求发送到follower服务器节点(若发送给Leader节点少了转发这一步)
2.首先会把事务请求转发给leader,
3.leader 服务器把客户端的失去请求转化成一个事务 Proposal(提议),并把这个 Proposal 分发给集群中的所有 Follower 服务器,
4.如果过半的follower节点同意(返回ACK)
5.Leader 就会再次向所有的Follower 服务器发送 Commit 消息,要求各个 follower 节点对前面的一个 Proposal 进行提交;
6.把最后的结果同步给Observer节点,
7.把结果返回给客户端。
serverId(服务器ID 既 myid)
-
比如有三台服务器,编号分别是1,2,3。
-
编号越大在选择算法中的权重越大。
zxid(最新的事物ID 既 LastLoggedZxid)
ZXID是一个事务ID,用来唯一标识一次服务器状态的变更。在某一个时刻,集群中每台机器的ZXID值不一定都一致。ZXID由2部分组成zxid是 64 位,高 32 位是 epoch 编号 低 32 位是counter消息计数器;
-
服务器中存放的最大数据ID。
-
ID值越大说明数据越新,在选举算法中数据越新权重越大。
epoch (逻辑时钟 既 PeerEpoch)
epoch:可以理解为当前集群所处的年代或者周期,每个leader 就像皇帝,都有自己的年号,所以每次改朝换代,leader 变更之后,都会在前一个年代的基础上加 1。这样就算旧的 leader 崩溃恢复之后,也没有人听他的了,因为follower 只听从当前年代的 leader 的命令。
counter消息计数器:每接收到一条事务消息这个值就+1
-
每个服务器都会给自己投票,或者叫投票次数,同一轮投票过程中的逻辑时钟值是相同的。
-
每投完一次票这个数据就会增加,然后与接收到的其它服务器返回的投票信息中的数值相比。
-
如果收到低于当前轮次的投票结果,该投票无效,需更新到当前轮次和当前的投票结果。