概述 git
最近在讀Designing Data-Intensive Application(簡稱DDIA)設計數據密集型應用,中文翻譯, 總體感受翻譯得仍是不錯的。讀到第九章《一致性與共識》的時候,裏面有對因果一致性的闡述,結合以前微信朋友圈技術負責人在2015年ArchSummit全球架構師峯會(相關的分享資料可從以下地方獲取)上關於朋友圈某一條狀態的評論以及評論的回覆,在跨數據中心(IDC)多副本間複製數據時,對因果一致性理論的應用,巧妙地解決了寫衝突的問題。咱們來看看因果一致性在實際業務開發中是如何應用的。算法
因果一致性的理解數據庫
下面咱們先就DDIA的內容來看一個簡單的問-答例子,並由此給因果關係下一個定義:微信
圖一、問-答的因果關係網絡
從上圖1可知,一個對話的觀察者(Observer)首先看到問題的答案「About ten seconds...」,而後纔看到被回答的問題「How far into the ...」。這是使人困惑的,由於它違背了咱們對因與果的直覺:若是一個問題被回答,顯然問題自己得先在那裏,由於給出答案的人必須已經看到這個問題,咱們認爲在問題和答案之間存在因果依賴。架構
考慮咱們設計這樣一個問答平臺,當有一個用戶去訪問數據,例如刷新最新的全部問-答列表,就像刷新知乎推薦頁面同樣,他必定要先看到問題,而後再看到答案,不然就會給用戶帶來很大的困擾。由於只看到答案,而沒有相應的問題是沒有實際的意義的。分佈式
正如DDIA所提到的,因果關係對事件施加了一種順序:因在果以前,消息發送在消息收取以前。並且就像現實生活中同樣,一件事會順序地致使另外一件事發生:某個節點讀取了一些數據而後寫入一些結果,另外一個節點讀取其寫入的內容,並依次寫入一些其餘內容等等。這些因果依賴的操做鏈定義了系統中的因果順序,即什麼在什麼以前發生。從而咱們也引出了分佈式系統的因果一致性,若是一個系統服從因果關係所規定的順序,咱們說它是因果一致性的。學習
微信朋友圈的因果一致性spa
下面咱們來看微信朋友圈某條狀態的評論以及對評論的答覆(也是評論)所構成的因果關係,以及微信是怎樣經過保證不一樣數據中心間的因果一致性來保證一個用戶在刷朋友圈的時候不會出現看到評論所對應的答覆,卻看不到答覆對應的評論。要理解下文的前提是必定要實事前去學習前文提到的:微信朋友圈技術負責人陳明在2015年ArchSummit全球架構師峯會上的分享資料。翻譯
圖二、微信分佈在全球四地的數據中心
從圖2微信分佈在全球四地的數據中心,可知用戶小王有兩個朋友:Mary、Kate,分別在不一樣的區域下(數據中心),因此他們要看到彼此朋友圈的內容時,必須等到相關的數據在不一樣數據中心間的副本同步到用戶所在的IDC完成以後才能看到。
圖3-一、數據在副本間同步時亂序
圖3-二、數據在副本間同步時亂序
從上圖3-一、3-2可知,因爲網絡在不一樣副本間複製數據時的延遲、中斷等分佈式系統中常見的場景,致使兩條消息在同步到用戶Kate(加拿大)所在數據中心上的副本時已經亂序了。即原先順序是這樣的:「Mary:這是哪裏?」->「小王:Mary,這是梅里雪山」,然而Kate去數據庫中查到的消息倒是這樣的順序:「小王:Mary,這是梅里雪山」->「Mary:這是哪裏?」,或者中間的某個時刻只能查詢到「小王:Mary,這是梅里雪山」這一條消息,你說Kate會不會懵逼。
爲了解決這個問題,微信是怎樣來處理的呢,且看下面分析。
圖4-一、因果關係的梳理
圖4-二、因果關係的梳理
從上圖4-一、4-2可知,咱們能夠將Mary對小王所發佈的朋友圈狀態的評論「Mary:這是哪裏?」當成因,而把小王對Mary評論的答覆「小王:Mary,這是梅里雪山」當成果。按照這樣的約定,當這兩條數據同步到Kate所在的數據中心副本時即便發生亂序,Kate根據在刷朋友圈時,根據因果關係也能夠將這個評論、答覆的順序調整到正確的、可閱讀的方式。那微信究竟是採用什麼方法來讓各個地區的用戶理解這個約定呢?具體來看:
圖五、朋友圈事件因果一致性的算法
從圖5咱們可知,微信採用以下的方案:
咱們能夠讀上面的三點背後的技術做出合理性的假設:
一、每條評論都有一個惟一的且遞增的數字ID:那麼背後確定是一個ID生成器,能夠全局惟一的入口,各個數據中心都必須來這個入口獲取。
二、每條新評論的ID都必須比本地已經見過的全局最大的ID大,確保因果關係:如上圖在香港的數據中心,當發表完2的評論,而且已經同步上海數據中心過來的1 4 7等ID的評論以後,若是再有香港地域下的用戶發表新評論時,那麼必定要大於當前香港數據中心能看到的全局最大ID,此時是7,因此香港地域此時用戶最新發表的評論的ID必須大於7(上圖有一個「跳過5」的備註),因此上圖中的ID(8)就是從這裏得出的。
三、廣播本地看到的全部評論和新評論到其它IDC;相同ID的評論合併排重:那麼何時廣播呢?其實就是本地域下的用戶針對同一條朋友圈狀態有評論時,該地域就負責申請一個全局ID,而後將這個評論的事件廣播給其餘的數據中心。注意這個過程須要合併全部看到的序列,例如香港數據中心就合併1 2 4 7 8等針對同一條朋友圈狀態的一系列評論事件IDs,而後再總體廣播出去,這樣才能保證針對同一條狀態的全部當前最新的事件總體被廣播出去,不然此時香港IDC只廣播8的話,若是前面的事件序列在廣播的中途丟失了,那麼其餘節點好比加拿大IDC就會漏掉部分評論事件,這也是數據多重補位的措施。固然這個方法有一個前提就是:由於同一個朋友圈的發佈狀態,通常的評論不會不少,因此形成的數據冗餘交互不會很大,不然是不行的。至於相同ID的評論合併排重,上圖5能夠看出,加拿大IDC會收到來自上海IDC的1 4 7事件系列,也會收到來自香港IDC同步過來的1 4 7 8 事件系列,這兩個廣播的事件系列有重複,因此須要去重。
總結
以上就是因果一致性在實際分佈式業務中的應用。