A. Zookeeper的腦裂問題及解決方案
先拋出一個問題:Zookeeper3.4.6版本是否存在腦裂問題?
一,什麼是腦裂
什麼是腦裂呢?
下圖是一個正常的Zookeeper集群,由7個節點組成。其中有1個Leader A和6個Follower。
當網路發送故障時,Follower D、Follower E、Follower F從集群中斷開了,然後這3個節點認為Leader掛了,然後重新選了1個Leader,Follower E變成了Leader B,如下圖,這就是腦裂。
上圖有可能存在一個問題,因為Zookeeper集群的一個特性是:過半節點存活可用。如何理解。網上有一個說法:有100個節點組成的集群,如果被網路分割成50和50兩個分區,那麼整個集群是不可用的,因為不滿足過半節點存活可用的原則。
二,Zookeeper3.4.6版本是否存在腦裂問題
首先,Zookeeper3.4.6不存在腦裂的問題。
為什麼呢?
Zookeeper3.4.6的選舉演算法是FastLeaderElection,該演算法的規則是投票超過半數的伺服器才能當選為Leader。這個演算法能夠保證leader的唯一性。
B. keepalived產生腦裂的原因與解決方法
原因
一般來說,裂腦的發生,有以下幾種原因:
1.高可用伺服器對之間心跳線鏈路發生故障,導致無法正常通信。
2.因心跳線壞了(包括斷了,老化)。
3.因網卡及相關驅動壞了,ip配置及沖突問題(網卡直連)。
4.因心跳線間連接的設備故障(網卡及交換機)。
5.因仲裁的機器出問題(採用仲裁的方案)。
6.高可用伺服器上開啟了 iptables防火牆阻擋了心跳消息傳輸。
7.高可用伺服器上心跳網卡地址等信息配置不正確,導致發送心跳失敗。
8.其他服務配置不當等原因,如心跳方式不同,心跳廣插沖突、軟體Bug等。
9.Keepalived配置里同一 VRRP實例如果 virtual_router_id兩端參數配置不一致也會導致裂腦問題發生。
解決方案
1.同時使用串列電纜和乙太網電纜連接,同時用兩條心跳線路,這樣一條線路壞了,另一個還是好的,依然能傳送心跳消息。
2.當檢測到裂腦時強行關閉一個心跳節點(這個功能需特殊設備支持,如Stonith、feyce)。相當於備節點接收不到心跳消患,通過單獨的線路發送關機命令關閉主節點的電源。
3.做好對裂腦的監控報警(如郵件及手機簡訊等或值班).在問題發生時人為第一時間介入仲裁,降低損失。例如,網路的監控報警短倍就有上行和下行的區別。報警消息發送到管理員手機上,管理員可以通過手機回復對應數字或簡單的字元串操作返回給伺服器.讓伺服器根據指令自動處理相應故障,這樣解決故障的時間更短.
C. keepalived腦裂現象
Keepalived的作用是檢測伺服器的狀態,如果有一台web伺服器宕機,或工作出現故障,Keepalived將檢測到,並將有故障的伺服器從系統中剔除,同時使用其他伺服器代替該伺服器的工作,當伺服器工作正常後Keepalived自動將伺服器加入到伺服器群中,這些工作全部自動完成,不需要人工干涉,需要人工做的只是修復故障的伺服器。
那麼keepalived是如何解決或者防止腦裂問題的?
我們首先要先知道腦裂產生的原因:
腦裂產生的原因:
一般來說,裂腦的發生,有以下幾種原因:
1.高可用伺服器對之間心跳線鏈路發生故障,導致無法正常通信。
2.因心跳線壞了(包括斷了,老化)。
3. 因網卡及相關驅動壞了,ip配置及沖突問題(網卡直連)。
4.因心跳線間連接的設備故障(網卡及交換機)。
5.因仲裁的機器出問題(採用仲裁的方案)。
6.高可用伺服器上開啟了 iptables防火牆阻擋了心跳消息傳輸。
7.高可用伺服器上心跳網卡地址等信息配置不正確,導致發送心跳失敗。
8.其他服務配置不當等原因,如心跳方式不同,心跳廣插沖突、軟體Bug等。
9.Keepalived配置里同一 VRRP實例如果virtual_router_id兩端參數配置不一致也會導致裂腦問題發生。
常見的解決方案:
在實際生產環境中,我們可以從以下幾個方面來防止裂腦問題的發生:
同時使用串列電纜和乙太網電纜連接,同時用兩條心跳線路,這樣一條線路壞了,另一個還是好的,依然能傳送心跳消息。
當檢測到裂腦時強行關閉一個心跳節點(這個功能需特殊設備支持,如Stonith、feyce)。相當於備節點接收不到心跳消患,通過單獨的線路發送關機命令關閉主節點的電源。
做好對裂腦的監控報警(如郵件及手機簡訊等或值班).在問題發生時人為第一時間介入仲裁,降低損失。例如,網路的監控報警短倍就有上行和下行的區別。報警消息發送到管理員手機上,管理員可以通過手機回復對應數字或簡單的字元串操作返回給伺服器.讓伺服器根據指令自動處理相應故障,這樣解決故障的時間更短.
當然,在實施高可用方案時,要根據業務實際需求確定是否能容忍這樣的損失。對於一般的網站常規業務.這個損失是可容忍的。
D. 如何防止ElasticSearch集群出現腦裂現象
有兩個參數可以減緩腦裂問題的出現:
discovery.zen.ping_timeout(默認值是3秒):默認情況下,一個節點會認為,如果master節點在3秒之內沒有應答,那麼這個節點就是死掉了,而增加這個值,會增加節點等待響應的時間,從一定程度上會減少誤判。
discovery.zen.minimum_master_nodes(默認是1):這個參數控制的是,一個節點需要看到的具有master節點資格的最小數量,然後才能在集群中做操作。官方的推薦值是(N/2)+1,其中N是具有master資格的節點的數量(我們的情況是3,因此這個參數設置為2,但對於只有2個節點的情況,設置為2就有些問題了,一個節點DOWN掉後,你肯定連不上2台伺服器了,這點需要注意)。
E. Zookeeper 理論基礎
ZooKeeper 由雅虎研究院開發,後來捐贈給了 Apache。ZooKeeper 是一個開源的分布式應用程序協調伺服器,其為分布式系統提供一致性服務。其一致性是通過基於 Paxos 演算法的ZAB 協議完成的。其主要功能包括:配置維護、域名服務、分布式同步、集群管理等。
zookeeper 的官網: http://zookeeper.apache.org
zk 是如何保證分布式系統的一致性的呢?是因為 zk 具有以下幾方面的特點:
對於zk 理論的學習,最重要也是最難的知識點就是 Paxos 演算法。所以我們首先學習 Paxos演算法。
Paxos 演算法是萊斯利·蘭伯特(Leslie Lamport)1990 年提出的一種基於消息傳遞的、具有高容錯性的一致性演算法。Google Chubby 的作者 Mike Burrows 說過,世上只有一種一致性演算法, 那就是 Paxos,所有其他一致性演算法都是 Paxos 演算法的不完整版。Paxos 演算法是一種公認的晦澀難懂的演算法,並且工程實現上也具有很大難度。較有名的 Paxos 工程實現有Google Chubby、ZAB、微信的 PhxPaxos 等。
Paxos 演算法是用於解決什麼問題的呢?Paxos 演算法要解決的問題是,在分布式系統中如何就某個決議達成一致。
拜占庭將軍問題是由 Paxos 演算法作者萊斯利·蘭伯特提出的點對點通信中的基本問題。該問題要說明的含義是,在不可靠信道上試圖通過消息傳遞的方式達到一致性是不可能的。所以,Paxos 演算法的前提是不存在拜占庭將軍問題,即信道是安全的、可靠的,集群節點間傳遞的消息是不會被篡改的。
一般情況下,分布式系統中各個節點間採用兩種通訊模型:共享內存(Shared Memory)、消息傳遞(Messages Passing)。而 Paxos 是基於消息傳遞通訊模型的。
在 Paxos 演算法中有三種角色,分別具有三種不同的行為。但很多時候,一個進程可能同時充當著多種角色。
Paxos 演算法的一致性主要體現在以下幾點:
Paxos 對於提案的提交演算法有兩種方案,2PC 與 3PC。
它們的區別主要就在於 accept 階段中是否包含 commit 功能。具體看下面的描述。
Paxos 演算法的 3PC 執行過程劃分為三個階段:准備階段 prepare、接受階段 accept,與提交階段 commit。
若提案者接收到的反饋數量超過了半數,則其會向外廣播兩類信息:
2PC 與 3PC 的區別是,在提案者接收到超過半數的表決者對於 parepare 階段的反饋後,其會向所有表決者發送真正的提案 proposal。當表決者接受到 proposal 後就直接將其同步到了本地,不用再等待 commit 消息了。
那麼,為什麼不直接使用 2PC,而要使用 3PC 呢?是因為 2PC 中存在著較多的弊端(這里就不再展開來說了)。所以很多 Paxos 工業實現使用的都是 3PC 提交。但 2PC 提交的效率要高於 3PC 提交,所以在保證不出問題的情況下,是可以使用 2PC 提交的。
前面所述的Paxos 演算法在實際工程應用過程中,根據不同的實際需求存在諸多不便之處, 所以也就出現了很多對於基本 Paxos 演算法的優化演算法,以對 Paxos 演算法進行改進,例如,Multi Paxos、Fast Paxos、EPaxos。
例如,Paxos 演算法存在「活鎖問題」,Fast Paxos 演算法對 Paxos 演算法進行了改進:只允許一個進程提交提案,即該進程具有對 N 的唯一操作權。該方式解決了「活鎖」問題。
ZAB ,Zookeeper Atomic Broadcast,zk 原子消息廣播協議,是專為 ZooKeeper 設計的一種支持崩潰恢復的原子廣播協議,在 Zookeeper 中,主要依賴 ZAB 協議來實現分布式數據一致性。
Zookeeper 使用一個單一主進程來接收並處理客戶端的所有事務請求,即寫請求。當伺服器數據的狀態發生變更後,集群採用 ZAB 原子廣播協議,以事務提案 Proposal 的形式廣播到所有的副本進程上。ZAB 協議能夠保證一個全局的變更序列,即可以為每一個事務分配一個全局的遞增編號 xid。
當 Zookeeper 客戶端連接到 Zookeeper 集群的一個節點後,若客戶端提交的是讀請求, 那麼當前節點就直接根據自己保存的數據對其進行響應;如果是寫請求且當前節點不是Leader,那麼節點就會將該寫請求轉發給 Leader,Leader 會以提案的方式廣播該寫操作,只要有超過半數節點同意該寫操作,則該寫操作請求就會被提交。然後 Leader 會再次廣播給所有訂閱者,即 Learner,通知它們同步數據。
ZAB 協議是 Paxos 演算法的一種工業實現演算法。但兩者的設計目標不太一樣。ZAB 協議主要用於構建一個高可用的分布式數據主從系統,即 Follower 是 Leader 的從機,Leader 掛了, 馬上就可以選舉出一個新的 Leader,但平時它們都對外提供服務。而 Fast Paxos 演算法則是用於構建一個分布式一致性狀態機系統,確保系統中各個節點的狀態都是一致的。
另外,ZAB 還使用 Google 的 Chubby 演算法作為分布式鎖的實現,而 Google 的 Chubby 也是 Paxos 演算法的應用。
zk 集群對於事務請求的處理是 Fast Paxos 演算法的體現,即只允許 Leader 提出提案。其屬於 3PC 提交。
但 Leader 選舉是 Paxos 演算法的體現,因為 Leader 宕機後,所有 Follower 均可提交提案, 它們在最初都是「我選我」。其屬於 2PC 提交。
為了避免 Zookeeper 的單點問題,zk 也是以集群的形式出現的。zk 集群中的角色主要有以下三類:
Learner:學習者,同步者。
Learner = Follower + Observer
QuorumPeer = Participant = Leader + Follower
在 ZAB 中有三個很重要的數據:
ZAB 協議中對zkServer 的狀態描述有三種模式。這三種模式並沒有十分明顯的界線,它們相互交織在一起。
zk 集群中的每一台主機,在不同的階段會處於不同的狀態。每一台主機具有四種狀態。
在集群啟動過程中,或 Leader 宕機後,集群就進入了恢復模式。恢復模式中最重要的階段就是 Leader 選舉。
A、serverId
這是zk 集群中伺服器的唯一標識,也稱為 sid,其實質就是 zk 中配置的 myid。例如, 有三個 zk 伺服器,那麼編號分別是 1,2,3。
B、 邏輯時鍾
邏輯時鍾,Logicalclock,是一個整型數,該概念在選舉時稱為 logicalclock,而在選舉結束後稱為epoch。即 epoch 與 logicalclock 是同一個值,在不同情況下的不同名稱。
在集群啟動過程中的 Leader 選舉過程(演算法)與 Leader 斷連後的 Leader 選舉過程稍微有一些區別,基本相同。
A、集群啟動中的 Leader 選舉
對於 Server1 而言,它的投票是(1, 0),接收 Server2 的投票為(2, 0)。其首先會比較兩者的 ZXID,均為 0,再比較 myid,此時 Server2 的 myid 最大,於是 Server1 更新自己的投票為(2, 0),然後重新投票。對於 Server2 而言,其無須更新自己的投票,只是再次向集群中所有主機發出上一次投票信息即可。
(4) 統計投票。每次投票後,伺服器都會統計投票信息,判斷是否已經有過半機器接受到相同的投票信息。對於 Server1、Server2 而言,都統計出集群中已經有兩台主機接受了(2, 0)的投票信息,此時便認為已經選出了新的 Leader,即 Server2。
(5) 改變伺服器狀態。一旦確定了 Leader,每個伺服器就會更新自己的狀態,如果是Follower,那麼就變更為 FOLLOWING,如果是 Leader,就變更為 LEADING。
(6) 添加主機。在新的 Leader 選舉出來後 Server3 啟動,其想發出新一輪的選舉。但由於當前集群中各個主機的狀態並不是 LOOKING,而是各司其職的正常服務,所以其只能是以Follower 的身份加入到集群中。
B、 宕機後的 Leader 選舉
在 Zookeeper 運行期間,Leader 與非 Leader 伺服器各司其職,即便當有非 Leader 伺服器宕機或新加入時也不會影響 Leader。但是若 Leader 伺服器掛了,那麼整個集群將暫停對外服務,進入新一輪的 Leader 選舉,其過程和啟動時期的 Leader 選舉過程基本一致。
前面我們說過,恢復模式具有兩個階段:Leader 選舉與初始化同步。當完成 Leader 選舉後,此時的 Leader 還是一個准 Leader,其要經過初始化同步後才能變為真正的 Leader。
具體過程如下:
當集群中的 Learner 完成了初始化狀態同步,那麼整個 zk 集群就進入到了正常工作模式了。
如果集群中的 Learner 節點收到客戶端的事務請求,那麼這些 Learner 會將請求轉發給Leader 伺服器。然後再執行如下的具體過程:
Observer 數量並不是越多越好,一般與 Follower 數量相同。因為 Observer 數量的增多雖不會增加事務操作壓力,但其需要從 Leader 同步數據,Observer 同步數據的時間是小於等於 Follower 同步數據的時間的。當 Follower 同步數據完成,Leader 的 Observer 列表中的Observer 主機將結束同步。那些完成同步的 Observer 將會進入到另一個對外提供服務的列表。那麼,那些沒有同步了數據無法提供服務的 Observer 主機就形成了資源浪費。
所以,對於事務操作發生頻繁的系統,不建議使用過多的 Observer。
Leader 中保存的 Observer 列表其實有兩個:
all:包含所有 Observer。
service:已經完成了從 Leader 同步數據的任務。service <= all。其是動態的。
Leader 中保存的 Follower 列表其實也有兩個:
all:要求其中必須有過半的 Follower 向Leader 反饋ACK
service:
當集群正在啟動過程中,或 Leader 崩潰後,集群就進入了恢復模式。對於要恢復的數據狀態需要遵循三個原則。
若集群中 Leader 收到的 Follower 心跳數量沒有過半,此時 Leader 會自認為自己與集群的連接已經出現了問題,其會主動修改自己的狀態為 LOOKING,去查找新的 Leader。
而其它 Server 由於有過半的主機認為已經丟失了 Leader,所以它們會發起新的 Leader選舉,選出一個新的 Leader。
正常情況下,當 Leader 收到超過半數 Follower 的 ACKs 後,就向各個 Follower 廣播COMMIT 消息,批准各個Server 執行該寫操作事務。當各個Server 在接收到Leader 的COMMIT 消息後就會在本地執行該寫操作,然後會向客戶端響應寫操作成功。
但是如果在非全部 Follower 收到 COMMIT 消息之前 Leader 就掛了,這將導致一種後果:部分 Server 已經執行了該事務,而部分 Server 尚未收到 COMMIT 消息,所以其並沒有執行該事務。當新的 Leader 被選舉出,集群經過恢復模式後需要保證所有 Server 上都執行了那些已經被部分 Server 執行過的事務。
當在 Leader 新事務已經通過,其已經將該事務更新到了本地,但所有 Follower 還都沒有收到 COMMIT 之前,Leader 宕機了,此時,所有 Follower 根本就不知道該 Proposal 的存在。當新的 Leader 選舉出來,整個集群進入正常服務狀態後,之前掛了的 Leader 主機重新啟動並注冊成為了 Follower。若那個別人根本不知道的 Proposal 還保留在那個主機,那麼其數據就會比其它主機多出了內容,導致整個系統狀態的不一致。所以,該 Proposa 應該被丟棄。類似這樣應該被丟棄的事務,是不能再次出現在集群中的,應該被清除。
前面我們說過,無論是寫操作投票,還是 Leader 選舉投票,都必須過半才能通過,也就是說若出現超過半數的主機宕機,則投票永遠無法通過。基於該理論,由 5 台主機構成的集群,最多隻允許 2 台宕機。而由 6 台構成的集群,其最多也只允許 2 台宕機。即,6 台與5 台的容災能力是相同的。基於此容災能力的原因,建議使用奇數台主機構成集群,以避免資源浪費。
但從系統吞吐量上說,6 台主機的性能一定是高於 5 台的。所以使用 6 台主機並不是資源浪費。
對於一個高可用的系統,除了要設置多台主機部署為一個集群避免單點問題外,還需要考慮將集群部署在多個機房、多個樓宇。對於多個機房、樓宇中集群也是不能隨意部署的, 下面就多個機房的部署進行分析。
在多機房部署設計中,要充分考慮「過半原則」,也就是說,盡量要確保 zk 集群中有過半的機器能夠正常運行。
在生產環境下,三機房部署是最常見的、容災性最好的部署方案。三機房部署中要求每個機房中的主機數量必須少於集群總數的一半。
zk 官方沒有給出較好的雙機房部署的容災方案。只能是讓其中一個機房佔有超過半數的主機,使其做為主機房,而另一機房少於半數。當然,若主機房出現問題,則整個集群會癱瘓。
CAP 定理又稱 CAP 原則,指的是在一個分布式系統中,Consistency(一致性)、Availability(可用性)、Partition tolerance(分區容錯性),三者不可兼得。
對於分布式系統,網路環境相對是不可控的,出現網路分區是不可避免的,因此系統必須具備分區容錯性。但其並不能同時保證一致性與可用性。CAP 原則對於一個分布式系統來說,只可能滿足兩項,即要麼 CP,要麼 AP。
BASE 是Basically Available(基本可用)、Soft state(軟狀態)和 Eventually consistent(最終一致性)三個短語的簡寫。
BASE 理論的核心思想是:即使無法做到實時一致性,但每個系統都可以根據自身的業務特點,採用適當的方式來使系統達到最終一致性。
基本可用是指分布式系統在出現不可預知故障的時候,允許損失部分可用性。
損失響應時間:
損失功能:
軟狀態,是指允許系統數據存在的中間狀態,並認為該中間狀態的存在不會影響系統的整體可用性,即允許系統主機間進行數據同步的過程存在一定延時。軟狀態,其實就是一種灰度狀態,過渡狀態。
最終一致性強調的是系統中所有的數據副本,在經過一段時間的同步後,最終能夠達到一個一致的狀態。因此,最終一致性的本質是需要系統保證最終數據能夠達到一致,而不需要實時保證系統數據的一致性。
從達到一致性的時間角度來劃分,可以分為:
單從客戶端訪問到的內容角度來劃分,可以分為:
zk 遵循的是 CP 原則,即保證了一致性,但犧牲了可用性。體現在哪裡呢?
當 Leader 宕機後,zk 集群會馬上進行新的 Leader 的選舉。但選舉時長一般在 200 毫秒內,最長不超過 60 秒,整個選舉期間 zk 集群是不接受客戶端的讀寫操作的,即 zk 集群是處於癱瘓狀態的。所以,其不滿足可用性。
這里說的zk可能會引發腦裂,是指的在多機房部署中,若出現了網路連接問題,形成多個分區,則可能會出現腦裂問題,可能會導致數據不一致。
(1)情況一
(2)情況二
(5)情況五
F. 什麼是Oracle Clusterware 和RAC中的腦裂
Oracle Clusterware就是oracle 集群,由多個節點組成。
RAC中的腦裂:每個節點都有一個私有IP,供集群內部通信和傳輸數據,我們叫做心跳,當心跳不通時,每個節點都會認為自己是好的,都會認為其他節點宕機了,集群就出現腦裂。解決腦裂的辦法去了解下votedisk
G. ORACLE 腦裂是什麼意思
針對OracleCluster,如果其中一個節點被踢出Cluster,無論是因為內部的同步問題,或是時間不一致等其他錯誤,只要有節點非人為的被踢出 Cluster就可以稱作腦裂.
H. ES集群搭建
一、集群搭建
1.前置操作
若克隆已有的es虛擬機,一定要清空一下文件:
2.配置集群,修改elasticsearch.yml
# 配置集群名稱,保證每個節點的名稱相同,如此就能都處於一個集群之內了
cluster.name: imooc-es-cluster
# 每一個節點的名稱,必須不一樣
node.name: es-node1
# http埠(使用默認即可)
http.port: 9200
# 主節點,作用主要是用於來管理整個集群,負責創建或刪除索引,管理其他非master節點(相當於企業老總)
node.master: true
# 數據節點,用於對文檔數據的增刪改查
node.data: true
# 集群列表(列出所有的其它伺服器ip)
discovery.seed_hosts: ["192.168.1.184", "192.168.1.185", "192.168.1.186"]
# 啟動的時候使用一個master節點
cluster.initial_master_nodes: ["es-node1"]
3.可查看剔除注釋的配置文件內容
more elasticsearch.yml | grep ^[^#]
4.分別啟動各個節點,後查看信息
二、集群腦裂
1.集群腦裂
如果發生網路中斷或者伺服器宕機,那麼集群會有可能被劃分為兩個部分,各自有自己的master管理,那麼這就是腦裂
伺服器1原為master,宕機後自己投票為master
2.解決方案
解決實現原理:半數以上的節點同意選舉,節點方可成為master
discovery.zen.minimum_master_nodes=(N/2)+1;
N為集群中master節點的數量,也就是node.master=true服務節點總數
3.ES7之後無此參數,已交由es自己管理