1. 程式人生 > >ZooKeeper 故障恢復

ZooKeeper 故障恢復

在介紹ZooKeeper處理節點故障的機制之前,我想先給大家講一講在一切都正常的情況下,ZooKeeper是如何工作的,也就是ZooKeeper處理客戶端請求的流程。當然我只側重講解客服端的寫請求部分。

過程如下:
這裡寫圖片描述
在這主要的6步過程中,任何與之相關的節點都有可能出現故障,那麼zooKeeper是如何來處理的呢,以保證服務的高可用性和一致性?

若ZooKeeper客戶端節點發生故障時,他正處於空閒狀態,則按照session失效處理。而複雜的情況是ZooKeeper客戶端節點發生故障是,他正在等待ZooKeeper伺服器端的請求響應。下面將對ZooKeeper客戶端節點發生故障的時機進行詳細的分類討論。

但是在此之前,我還想簡單的介紹一下ZooKeeper中session的概念。我們知道ZooKeeper允許客戶端建立兩種型別的節點:persistent、ephemeral,ephemeral型別的節點是與建立它的客戶端一起共存亡的。那麼這中間就有問題,ZooKeeper是如何知道客戶端還存不存在呢?ZooKeeper是使用session來解決這個問題的,這也是為什麼我們在客戶端建立ZooKeeper例項時需要傳入一個sessionout的引數。當客戶端與Follower連線時,實際上是成功建立了一個session,Follower和Leader都儲存了這個session資訊(實際上Session的建立也是需要Leader同意的)。一方面,客戶端會定期的向Follower傳送Ping包來告訴這個Follower我還活著;另一方面,Leader也會定期向Follower傳送ping包,一則檢測它的Follower們是否至少有超過一半還活著,二則Follower們返回他們各自正在服務的客戶端(未超時的session),來告訴Leader那些客戶端還活著,這樣Leader就可以刪除那些客戶端已經不存在的ephemeral型別的節點。ok,關於這個session問題我們先暫時討論到這裡,下面我們來看看當正在工作的客戶端節點發生故障的,ZooKeeper系統是如何來處理的吧。

1.Follower在第2步時若沒有發現客戶端已經發生了故障,則他會進行第2步,否則,他將會丟棄該客戶端的請求包。

2.Leader在第3步時還沒有發現客戶端已經發生了故障,那麼後面的第4、5步都會順利執行。對於第6步,若此時Follower已經發現了該客戶端已發生故障,則它不會向客戶端傳送響應包,而直接從FinalRequestProcessor處理器中返回;若此時Follower還沒有發現該客戶端已發生故障,則FinalRequestProcessor會將響應包交給對應的NIOServerCnxn,而NIOServerCnxn在傳送該響應包時,會丟擲異常,但並沒有對該異常做任何處理。

3.Leader在第3步時發現了客戶端已經發生了故障,那麼後面的第4、5步都會順利執行,只不過此時的操作型別就是OpCode.error,然後直接從FinalRequestProcessor處理器中返回,而不會發生第6步了。

4.從上面的分析我們可以看出,第4、5步並不會收到客戶端是否發生故障的影響。

我們知道,當某一個Follower或Observer發生故障時,與之直接相連的ZooKeeper客戶端就不可能再從Follower或Observer收到正在處理的請求的響應包,因此,它會丟棄正在處理的請求,並通知客戶。而ZooKeeper客戶端則會重新選擇一個Follower或Observer,並與之建立聯絡為客戶端服務,請注意,這個過程對使用者是透明的。

1.Follower在處理第2步之前發生故障,則處理情況如上所訴,只涉及到ZooKeeper客戶端;若Follower在處理第2步之後發生故障,則,Leader最遲會在執行第3步的時候發現Follower發生了故障,儘管Leader傳送的提案和提交,Follower收不到,Leader也不會收到Follower的投票,但這並不會影響Leader的處理,只要當前還有超過半數的follower存活著。

2.從上可以看出,單個Follower節點的實效對整個ZooKeeper服務叢集根本就不會產生“任何”的影響,所以單個Follower在任何時刻的失效,系統仍然會比較穩定的繼續執行。

在這裡,可能有些人會問,如果某一個Follower實效,則Leader就不能得到該Follower管理的session的資訊,之後Leader可能會誤認為與該Follower相連的若干ZooKeeper客戶端實效。沒錯,是這樣的,但這種情況的處理同ZooKeeper客戶端發生故障是一樣的。

最後,我就想討論一下Leader節點發生故障的情況下,ZooKeeper的處理機制。

1.若Leader節點在第2步之前發生了故障,則Follower的第2步不會執行成功,但該請求包被新增到了Follower的pendingSyncs集合中,同時Follower再次之前就已經發現Leader已經實失效,退出Follower角色,同時關閉與之相連的客戶端,並不在。之後,Follower就會參入Leader的選舉中,而在選舉的過程中,該節點不會再接受任何客戶端的連線。

2.若Leader節點在第2步之後,第3步之前發生了故障,處理同1。

3.若Leader節點在第3步之後,第4步之前發生了故障,處理同1。

4.若Leader節點在第4步之後,第5步之前發生了故障,處理同1。

5.若Leader節點在第5步之後,第6步之前發生了故障,則Folloer的處理同1的同時,也會執行第6步操作。