1. 程式人生 > >網易視訊雲:分散式轉碼服務高可用淺析

網易視訊雲:分散式轉碼服務高可用淺析

  分散式視訊處理系統中的worker、razer、sdk等模組以無狀態方式設計,即worker應用停止服務或節點宕機均不會影響整個系統對於視訊的處理。比如有worker-N應用正在處理轉碼,到了99%的時候,卻很不幸的應用崩潰,顯然該轉碼任務失敗,那麼我們該怎麼來保證該轉碼任務能正常結束,讓使用者不吐槽?我們的節點管理中心即Node Manager應此而生,它全程監控轉碼任務的狀態,如碰到系統因素引起的失敗,進行任務回收,其他worker應用重新進行轉碼。

  節點管理中心最基本核心的功能為各個節點伺服器的狀態管理,此外還包括使用者管理(包括鑑權)、任務的跟蹤統計、節點狀態變更通知、資源監控、全域性配置資訊獲取、及自身的HA等功能,如下圖所示。




  在設計之初,各個任務節點能獨立執行不依賴與管理中心,即管理中心是單點執行狀態。但是隨著功能的不斷完善及設計的不斷優化,我們發現單點狀態已經連最起碼的功能完整性都保證不了了,比如統計資料混亂、dashbord平臺無法使用、監控報警失效,節點失效通知不及時等等,因此我們對Node Manager提出了高可用性的需求,也就是本文的初衷。

  眾所周知,在分散式高可用性系統模型方面無非就是中心化和去中心化兩種設計方式。中心化的設計例如mysql的MSS單主雙從、MongDB Master、HDFS NameNode、MapReduce JobTracker等,有1個或幾個節點充當整個系統的核心元資料及節點管理工作,其他節點都和中心節點互動。這種方式的好處顯而易見,資料和管理高度統一集中在一個地方,容易聚合,就像領導者一樣,其他人都服從就好,簡單可行。但是缺點是模組高度集中,容易形成效能瓶頸,並且如果出現異常,就像群龍無首一樣。無中心化的設計,例如cassandra、zookeeper,系統中不存在一個領導者,節點彼此通訊並且彼此合作完成任務。好處在於如果出現異常,不會影響整體系統,僅僅區域性不可用。缺點是比較協議複雜,而且需要各個節點間同步資訊。


  節點管理中心由於不涉及到使用者(2C)的相關操作操作,訪問量及併發量都較為有限,所以我們總結出了JDBC Store active/standby的中心化高可用實現方案,通過JDBC的方式與database互動,使用database的表級排它鎖來實現多節點爭搶主機節點,另外還包括節點狀態轉變(active/standby切換)和客戶端的failover機制。以下分別通過elect leader、status change和client failover分別進行闡述。

  elect leader詞彙據我所知是從zookeeper裡來的,保證叢集中Master的可用性和唯一性。我們的高可用性方案是active/standby,但是因為我的膚淺實在想不出更好的名詞來表達這個爭搶主機這個過程,本文中涉及於此,都會以elect leader來進行描述。


  兩個節點管理應用同時啟動,我們需要確定一個唯一的應用來服務於其他業務節點,在這之前我們需要建立csserver_ha表用於儲存主機節點的資訊,elect leader的主要流程如下:



  √Lock csserver_ha。

  √查詢csserver_ha中ha_status = ‘active’的記錄數。

  √若結果為0說明首次啟動,則往csserver_ha新增一條記錄包括該應用所在的IP、port、心跳時間(當前時間),狀態為active,然後setActive(this),也就是說把該節點應用設定為主機。

  √若結果大於0,說明之前已存在過active的節點應用,此時獲取狀態為active的記錄,判斷當前和該記錄中的心跳時間(hb_time)的差值。

  √若小於預設值的timeout時間,說明之前存在的active應用尚未失效,則seStandby(this),也就是設定該節點應用為備機。

  √若大於等於 timeout時間,說明之前存在的active應用已經失效,那麼設定該節點應用為主機,即setActive (this)。更新csserver_ha 中active記錄的ip、port、hb_time為當前應用資訊和當前時間。

  √Unlock csserver_ha。

  Status change表示節點應用的內部狀態轉變,分別為dead、active、standby,dead表示節點處於宕機或者應用例項未啟動,active表示應用例項為主機,standby表示應用例項為備機。

  √當主機轉變為active時,其他任務單元方能與之正確通訊,並且自啟動心跳日誌記錄任務和腦裂檢測任務。定時寫心跳日誌到表csserver_hb中,表示該節點應用尚淺存活。如果叢集單元發生“腦裂”,那麼可想而知會發生存在兩個主機節點的情況,其他任務單元提交的資料也被割裂,得不到完整性的保障。在我們的系統中,如果active節點和資料庫之間發生網路中斷,standby檢測到active不可用(假死或者宕機),立即接管服務,轉變為active,顯然這個時候有2個active了,那怎麼去保證呢?也就是前文所說的腦裂檢測任務,active節點不斷的去詢問standby節點“你是誰?”,standby節點如果回答“I am active”,那麼active節點降級成standby節點。或者active節點和standby節點也發生網路中斷了,這種情況下,雙active很有可能會出現,為了保證系統對於節點管理中心的唯一性,active節點降級轉變成standby節點。

  √當主機轉變為standby時,其他節點與之通訊返回“服務不可用”的錯誤碼。standby節點啟動針對active節點的健康檢測,主要是不斷的讀取active記錄中的心跳時間hb_time,如果和當前時間的差值超出預先設定的timeout時間,則表示active節點不可用,至此standby節點切換成active狀態。Standby扮演著try get the active的角色。

  √如果active和standby節點與資料庫的網路均處於中斷狀態,那麼意味著節點管理中心叢集崩潰。

  Client failover任務單元訪問節點管理中心時需遵循failover:{ip1:port1;ip2:port2}的協議,client端輪詢訪問ip1和ip2,不需要去區分active和standby,若返回“服務不可用”的狀態碼或者網路連線超時就去重試訪問另外一個,如果ip1和ip2均不可用,則說明節點管理中心叢集崩潰。

  本文僅限於討論小眾範疇的通過MySql共享儲存方式實現高可用方案,其他的例如Keepalived、Zookeeper等實現及文中所涉及的高可用、腦裂、網路分割槽等概念,讀者可自行Google。