zookeeper兩個經典問題-帶著問題看原始碼
阿新 • • 發佈:2019-02-14
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 longstartForwarding(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)
例如 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