zookeeper两个经典问题-带着问题看源码

本文探讨了ZooKeeper集群中Leader与Follower之间的数据同步流程。解析了当Follower断开后重新连接时的数据同步机制,并分析了同步过程中可能遇到的问题及解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 机器1,机器2,机器3.

   机器3是Leader.

   机器3接受到a,b,c消息.

   机器2接受到a的proposal和commit. 没有收到b的消息.

   当收到c的proposal和commit时会怎么办? 数据是否错乱?

2. zk数据同步是拉取还是推送?

3.机器1,2,机器3

机器3是Leader. 机器2断开了. 机器2重新选举,连接到Leader上,同步相关数据.

相关代码如下:

线程A:

synchronized public void processSync(LearnerSyncRequest r){
synchronized public long startForwarding(LearnerHandler handler,...){
 ...
  addForwardingFollower(handler);  //加入到转发队列之后,leader才会将proposal和commit数据提交.
...
}
synchronized public void processAck(long sid, long zxid, SocketAddress followerAddr) {}

线程B:

/**
 * send a packet to all the followers ready to follow
 * 
 * @param qp
 *                the packet to be sent
 */
void sendPacket(QuorumPacket qp) {
    synchronized (forwardingFollowers) {
        for (LearnerHandler f : forwardingFollowers) {                
            f.queuePacket(qp);
        }
    }
}
  • Leader.sendPacket(QuorumPacket) (org.apache.zookeeper.server.quorum)
  •   调用方1 Leader.propose(Request) (org.apache.zookeeper.server.quorum)
  •   调用方1 Leader.commit(long) (org.apache.zookeeper.server.quorum)
 同步数据推送完毕,但是因为时间差后续新的proposal请求和commit又没有推送给Follower.

  例如 Leader 有 a(已提交) b(已多数通过但未提交) c(已prososal但未多数通过) 三个消息.

    此时Follower将三个数据都同步过来. 此时Leader对c进行commit, 又接受了一个d的proposal. 都没有发到机器2.

   此时机器2上的 queuedList为 a,b,c ; commitList为a,b;

   然后Leader收到d的半数通过,发给机器2 d的commit ;

   此时机器2上的 queuedList为 a,b,c ; commitList为a,b d.

  请问这种情况会发生么?



答案:

1.答案在zookeeper的源代码实现里.

    zk依赖于长连接进行集群间通信.

     一旦数据没有发送到,就代表连接断了. 抛异常,重启.

2.

线程A:

synchronized public void processSync(LearnerSyncRequest r){
synchronized public long startForwarding(LearnerHandler handler,...){
 ...
  addForwardingFollower(handler);  //加入到转发队列之后,leader才会将proposal和commit数据提交.
...
}
synchronized public void processAck(long sid, long zxid, SocketAddress followerAddr) {}

线程B:

/**
 * send a packet to all the followers ready to follow
 * 
 * @param qp
 *                the packet to be sent
 */
void sendPacket(QuorumPacket qp) {
    synchronized (forwardingFollowers) {
        for (LearnerHandler f : forwardingFollowers) {                
            f.queuePacket(qp);
        }
    }
}
  • Leader.sendPacket(QuorumPacket) (org.apache.zookeeper.server.quorum)
  •   调用方1 Leader.propose(Request) (org.apache.zookeeper.server.quorum)
  •   调用方1 Leader.commit(long) (org.apache.zookeeper.server.quorum)

不会因为有锁.

  消息c的commit肯定会同步给机器2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值