隨筆 - 16  文章 - 1  trackbacks - 0
          <2025年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          常用鏈接

          留言簿

          隨筆檔案

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          Two-phase commit(http://en.wikipedia.org/wiki/Two-phase_commit_protocol)是分布式事務(wù)最基礎(chǔ)的協(xié)議,Three-phase commit(http://en.wikipedia.org/wiki/Three-phase_commit_protocol)主要解決Two-phase commit中協(xié)調(diào)者宕機問題。

          Two-phase commit的算法實現(xiàn) (from <<Distributed System: Principles and Paradigms>>):

          協(xié)調(diào)者(Coordinator):

              write START_2PC to local log;

              multicast VOTE_REQUEST to all participants;

              while not all votes have been collected {

                  wait for any incoming vote;

                  if timeout {

                      write GLOBAL_ABORT to local log;

                      multicast GLOBAL_ABORT to all participants;

                      exit;

                  }

                  record vote;

              }

              if all participants sent VOTE_COMMIT and coordinator votes COMMIT {

                  write GLOBAL_COMMIT to local log;

                  multicast GLOBAL_COMMIT to all participants;

              } else {

                  write GLOBAL_ABORT to local log;

                  multicast GLOBAL_ABORT to all participants;

              }

          參與者(Participants)

              write INIT to local log;

              wait for VOTE_REQUEST from coordinator;

              if timeout {

                  write VOTE_ABORT to local log;

                  exit;

              }

              if participant votes COMMIT {

                  write VOTE_COMMIT to local log;

                  send VOTE_COMMIT to coordinator;

                  wait for DECISION from coordinator;

                  if timeout {

                      multicast DECISION_REQUEST to other participants;

                      wait until DECISION is received;  /* remain blocked*/

                      write DECISION to local log;

                  }

                  if DECISION == GLOBAL_COMMIT

                      write GLOBAL_COMMIT to local log;

                  else if DECISION == GLOBAL_ABORT

                      write GLOBAL_ABORT to local log;

              } else {

                  write VOTE_ABORT to local log;

                  send VOTE_ABORT to coordinator;

              }

          另外,每個參與者維護一個線程專門處理其它參與者的DECISION_REQUEST請求,處理線程流程如下:

              while true {

                  wait until any incoming DECISION_REQUEST is received;

                  read most recently recorded STATE from the local log;

                  if STATE == GLOBAL_COMMIT

                      send GLOBAL_COMMIT to requesting participant;

                  else if STATE == INIT or STATE == GLOBAL_ABORT;

                      send GLOBAL_ABORT to requesting participant;

                  else

                      skip;  /* participant remains blocked */

              }

          從上述的協(xié)調(diào)者與參與者的流程可以看出,如果所有參與者VOTE_COMMIT后協(xié)調(diào)者宕機,這個時候每個參與者都無法單獨決定全局事務(wù)的最終結(jié)果(GLOBAL_COMMIT還是GLOBAL_ABORT),也無法從其它參與者獲取,整個事務(wù)一直阻塞到協(xié)調(diào)者恢復(fù);如果協(xié)調(diào)者出現(xiàn)類似磁盤壞這種永久性錯誤,該事務(wù)將成為被永久遺棄的孤兒。問題的解決有如下思路:

          1. 協(xié)調(diào)者持久化數(shù)據(jù)定期備份。為了防止協(xié)調(diào)者出現(xiàn)永久性錯誤,這是一種代價最小的解決方法,不容易引入bug,但是事務(wù)被阻塞的時間可能特別長,比較適合銀行這種正確性高于一切的系統(tǒng)。

          2. Three-phase Commit。這是理論上的一種方法,實現(xiàn)起來復(fù)雜且效率低。思路如下:假設(shè)參與者機器不可能出現(xiàn)超過一半同時宕機的情況,如果協(xié)調(diào)者宕機,我們需要從活著的超過一半的參與者中得出事務(wù)的全局結(jié)果。由于不可能知道已經(jīng)宕機的參與者的狀態(tài),所以引入一個新的參與者狀態(tài)PRECOMMIT,參與者成功執(zhí)行一個事務(wù)需要經(jīng)過INIT, READY, PRECOMMIT,最后到COMMIT狀態(tài);如果至少有一個參與者處于PRECOMMIT或者COMMIT,事務(wù)成功;如果至少一個參與者處于INIT或者ABORT,事務(wù)失??;如果所有的參與者都處于READY(至少一半?yún)⑴c者活著),事務(wù)失敗,即使原先宕機的參與者恢復(fù)后處于PRECOMMIT狀態(tài),也會因為有其它參與者處于ABORT狀態(tài)而回滾。PRECOMMIT狀態(tài)的引入給了宕機的參與者回滾機會,所以Three-phase commit在超過一半的參與者活著的時候是不阻塞的。不過,Three-phase Commit只能算是是理論上的探索,效率低并且沒有解決網(wǎng)絡(luò)分區(qū)問題。

          3. Paxos解決協(xié)調(diào)者單點問題。Jim Gray和Lamport合作了一篇論文講這個方法,很適合互聯(lián)網(wǎng)公司的超大規(guī)模集群,Google的Megastore事務(wù)就是這樣實現(xiàn)的,不過問題在于Paxos和Two-phase Commit都不簡單,需要有比較靠譜(代碼質(zhì)量高)的小團隊設(shè)計和編碼才行。后續(xù)的blog將詳細闡述該方法。

          總之,分布式事務(wù)只能是系統(tǒng)開發(fā)者的烏托邦式理想,Two-phase commit的介入將導(dǎo)致涉及多臺機器的事務(wù)之間完全串行,沒有代價的分布式事務(wù)是不存在的。

           

          posted @ 2009-12-22 23:01 Programmers 閱讀(856) | 評論 (0)編輯 收藏

          前面我的一篇文章http://hi.baidu.com/knuthocean/blog/item/12bb9f3dea0e400abba1673c.html引用了對Google App Engine工程師關(guān)于Bigtable/Megastore replication的文章。當(dāng)時留下了很多疑問,比如:為什么Google Bigtable 是按照column family級別而不是按行執(zhí)行replication的?今天重新思考了Bigtable replication問題,有如下體會:

          1. Bigtable/GFS的設(shè)計屬于分層設(shè)計,和文件系統(tǒng)/數(shù)據(jù)庫分層設(shè)計原理一致,通過系統(tǒng)隔離解決工程上的問題。這種分層設(shè)計帶來了兩個問題,一個是性能問題,另外一個就是Replication問題。由于存儲節(jié)點和服務(wù)節(jié)點可能不在一臺機器,理論上總是存在性能問題,這就要求我們在加載/遷移Bigtable子表(Bigtable tablet)的時候考慮本地化因素;另外,GFS有自己的replication機制保證存儲的可靠性,Bigtable通過分離服務(wù)節(jié)點和存儲節(jié)點獲得了很大的靈活性,且Bigtable的宕機恢復(fù)時間可以做到很短。對于很多對實時性要求不是特別高的應(yīng)用Bigtable由于服務(wù)節(jié)點同時只有一個,既節(jié)約資源又避免了單點問題。然后,Bigtable tablet服務(wù)過于靈活導(dǎo)致replication做起來極其困難。比如,tablet的分裂和合并機制導(dǎo)致多個tablet(一個只寫,其它只讀)服務(wù)同一段范圍的數(shù)據(jù)變得幾乎不可能。

          2. Google replication分為兩種機制,基于客戶端和基于Tablet Server。分述如下:

          2-1). 基于客戶端的replication。這種機制比較簡單,實現(xiàn)如下:客戶端讀/寫操作均為異步操作,每個寫操作都嘗試寫兩個Bigtable集群,任何一個寫成功就返回用戶,客戶端維護一個retry list,不斷重試失敗的寫操作。讀操作發(fā)到兩個集群,任何一個集群讀取成功均可。然后,這樣做有兩個問題:

              a. 客戶端不可靠,可能因為各種問題,包括程序問題退出,retry list丟失導(dǎo)致兩個集群的數(shù)據(jù)不一致;

              b. 多個客戶端并發(fā)操作時無法保證順序性。集群A收到的寫操作可能是"DEL item; PUT item";集群B的可能是"PUT item; DEL item"。

          2-2). 基于Tablet Server的replication。這種機制實現(xiàn)較為復(fù)雜,目的是為了保證讀服務(wù),寫操作的延時仍然可能比較長。兩個集群,一個為主集群,提供讀/寫服務(wù);一個為slave集群,提供只讀服務(wù),兩個集群維持最終一致性。對于一般的讀操作,盡量讀取主集群,如果主集群不可以訪問則讀取slave集群;對于寫操作,首先將寫操作提交到主集群的Tablet Server,主集群的Tablet Server維護slave集群的元數(shù)據(jù)信息,并維護一個后臺線程不斷地將積攢的用戶表格寫操作提交到slave集群進行日志回放(group commit)。對于一般的tablet遷移,操作邏輯和Bigtable論文中的完全一致;主集群如果發(fā)生了機器宕機,則除了回放commit log外,還需要完成宕機的Tablet Server遺留的后臺備份任務(wù)。之所以要按照column family級別而不是按行復(fù)制,是為了提高壓縮率從而提高備份效率。如果主集群寫操作日志的壓縮率大于備份數(shù)據(jù)的壓縮率,則可能出現(xiàn)備份不及時,待備份數(shù)據(jù)越來越多的問題。

          假設(shè)集群A為主集群,集群B是集群A的備份,集群切換時先停止集群A的寫服務(wù),將集群A余下的備份任務(wù)備份到集群B后切換到集群B;如果集群A不可訪問的時間不可預(yù)知,可以選擇直接切換到集群B,這樣會帶來一致性問題。且由于Bigtable是按列復(fù)制的,最后寫入的一些行的事務(wù)性無法保證。不過由于寫操作數(shù)據(jù)還是保存在集群A的,所以用戶可以知道丟了哪些數(shù)據(jù),很多應(yīng)用可以通過重新執(zhí)行A集群遺留的寫操作進行災(zāi)難恢復(fù)。Google的App Engine也提供了這種查詢及重做丟失的寫操作的工具。

          想法不成熟,有問題聯(lián)系:knuthocean@163.com

          posted @ 2009-12-18 22:05 Programmers 閱讀(388) | 評論 (0)編輯 收藏

          負載平衡策略

          Dynamo的負載平衡取決于如何給每臺機器分配虛擬節(jié)點號。由于集群環(huán)境的異構(gòu)性,每臺物理機器包含多個虛擬節(jié)點。一般有如下兩種分配節(jié)點號的方法:

          1. 隨機分配。每臺物理節(jié)點加入時根據(jù)其配置情況隨機分配S個Token(節(jié)點號)。這種方法的負載平衡效果還是不錯的,因為自然界的數(shù)據(jù)大致是比較隨機的,雖然可能出現(xiàn)某段范圍的數(shù)據(jù)特別多的情況(如baidu, sina等域名下的網(wǎng)頁特別多),但是只要切分足夠細,即S足夠大,負載還是比較均衡的。這個方法的問題是可控性較差,新節(jié)點加入/離開系統(tǒng)時,集群中的原有節(jié)點都需要掃描所有的數(shù)據(jù)從而找出屬于新節(jié)點的數(shù)據(jù),Merkle Tree也需要全部更新;另外,增量歸檔/備份變得幾乎不可能。

          2. 數(shù)據(jù)范圍等分+隨機分配。為了解決方法1的問題,首先將數(shù)據(jù)的Hash空間等分為Q = N * S份 (N=機器個數(shù),S=每臺機器的虛擬節(jié)點數(shù)),然后每臺機器隨機選擇S個分割點作為Token。和方法1一樣,這種方法的負載也比較均衡,且每臺機器都可以對屬于每個范圍的數(shù)據(jù)維護一個邏輯上的Merkle Tree,新節(jié)點加入/離開時只需掃描部分數(shù)據(jù)進行同步,并更新這部分數(shù)據(jù)對應(yīng)的邏輯Merkle Tree,增量歸檔也變得簡單。該方法的一個問題是對機器規(guī)模需要做出比較合適的預(yù)估,隨著業(yè)務(wù)量的增長,可能需要重新對數(shù)據(jù)進行劃分。

          不管采用哪種方法,Dynamo的負載平衡效果還是值得擔(dān)心的。

          客戶端緩存及前后臺任務(wù)資源分配

          客戶端緩存機器信息可以減少一次在DHT中定位目標(biāo)機器的網(wǎng)絡(luò)交互。由于客戶端數(shù)量不可控,這里緩存采用客戶端pull的方式更新,Dynamo中每隔10s或者讀/寫操作發(fā)現(xiàn)緩存信息不一致時客戶端更新一次緩存信息。

          Dynamo中同步操作、寫操作重試等后臺任務(wù)較多,為了不影響正常的讀寫服務(wù),需要對后臺任務(wù)能夠使用的資源做出限制。Dynamo中維護一個資源授權(quán)系統(tǒng)。該系統(tǒng)將整個機器的資源切分成多個片,監(jiān)控60s內(nèi)的磁盤讀寫響應(yīng)時間,事務(wù)超時時間及鎖沖突情況,根據(jù)監(jiān)控信息算出機器負載從而動態(tài)調(diào)整分配給后臺任務(wù)的資源片個數(shù)。

          Dynamo的優(yōu)點

          1. 設(shè)計簡單,組合利用P2P的各種成熟技術(shù),模塊劃分好,代碼復(fù)用程度高。

          2. 分布式邏輯與單機存儲引擎邏輯基本隔離。很多公司有自己的單機存儲引擎,可以借鑒Dynamo的思想加入分布式功能。

          3. NWR策略可以根據(jù)應(yīng)用自由調(diào)整,這個思想已經(jīng)被Google借鑒到其下一代存儲基礎(chǔ)設(shè)施中。

          4. 設(shè)計上天然沒有單點,且基本沒有對系統(tǒng)時鐘一致性的依賴。而在Google的單Master設(shè)計中,Master是單點,需要引入復(fù)雜的分布式鎖機制來解決,且Lease機制需要對機器間時鐘同步做出假設(shè)。

          Dynamo的缺陷

          1. 負載平衡相比單Master設(shè)計較不可控;負載平衡策略一般需要預(yù)估機器規(guī)模,不能無縫地適應(yīng)業(yè)務(wù)動態(tài)增長。

          2. 系統(tǒng)的擴展性較差。由于增加機器需要給機器分配DHT算法所需的編號,操作復(fù)雜度較高,且每臺機器存儲了整個集群的機器信息及數(shù)據(jù)文件的Merkle Tree信息,機器最大規(guī)模只能到幾千臺。

          3. 數(shù)據(jù)一致性問題。多個客戶端的寫操作有順序問題,而在GFS中可以通過只允許Append操作得到一個比較好的一致性模型。

          4. 數(shù)據(jù)存儲不是有序,無法執(zhí)行Mapreduce;Mapreduce是目前允許機器故障,具有強擴展性的最好的并行計算模型,且有開源的Hadoop可以直接使用,Dynamo由于數(shù)據(jù)存儲依賴Hash無法直接執(zhí)行Mapreduce任務(wù)。

           

          posted @ 2009-12-05 15:19 Programmers 閱讀(1778) | 評論 (0)編輯 收藏

          異常處理

          Dynamo中把異常分為兩種類型,臨時性的異常和永久性異常。服務(wù)器程序運行時一般通過類似supervise的監(jiān)控daemon啟動,出現(xiàn)core dump等異常情況時自動重啟。這種異常是臨時性的,其它異常如硬盤報修或機器報廢等由于其持續(xù)時間太長,稱之為永久性的?;仡橠ynamo的設(shè)計,一份數(shù)據(jù)被寫到N, N+1, ... N+K-1這K臺機器上,如果機器N+i (0 <= i <= K-1)宕機,原本寫入該機器的數(shù)據(jù)轉(zhuǎn)移到機器N+K,機器N+K定時ping機器N+i,如果在指定的時間T內(nèi)N+i重新提供服務(wù),機器N+K將啟動傳輸任務(wù)將暫存的數(shù)據(jù)發(fā)送給機器N+i;如果超過了時間T機器N+i還是處于宕機狀態(tài),這種異常被認為是永久性的,這時需要借助Merkle Tree機制進行數(shù)據(jù)同步。這里的問題在于時間T的選擇,所以Dynamo的開發(fā)人員后來干脆把所有程序檢測出來的異常認為是臨時性的,并提供給管理員一個utility工具,用來顯示指定一臺機器永久性下線。由于數(shù)據(jù)被存儲了K份,一臺機器下線將導(dǎo)致后續(xù)的K臺機器出現(xiàn)數(shù)據(jù)不一致的情況。這是因為原本屬于機器N的數(shù)據(jù)由于機器下線可能被臨時寫入機器N+1, ... N+K。如果機器N出現(xiàn)永久性異常,后續(xù)的K臺機器都需要服務(wù)它的部分數(shù)據(jù),這時它們都需要選擇冗余機器中較為空閑的一臺進行同步。Merkle Tree同步的原理很簡單,每個非葉子節(jié)點對應(yīng)多個文件,為其所有子節(jié)點值組合以后的Hash值,葉子節(jié)點對應(yīng)單個數(shù)據(jù)文件,為文件內(nèi)容的Hash值。這樣,任何一個數(shù)據(jù)文件不匹配都將導(dǎo)致從該文件對應(yīng)的葉子節(jié)點到根節(jié)點的所有節(jié)點值不同。每臺機器維護K棵Merkle Tree,機器同步時首先傳輸Merkle Tree信息,并且只需要同步從根到葉子的所有節(jié)點值均不相同的文件。

          讀/寫流程

          客戶端的讀/寫請求首先傳輸?shù)骄彺娴囊慌_機器,根據(jù)預(yù)先配置的K、W和R值,對于寫請求,根據(jù)DHT算法計算出數(shù)據(jù)所屬的節(jié)點后直接寫入后續(xù)的K個節(jié)點,等到W個節(jié)點返回成功時返回客戶端,如果寫請求失敗將加入retry_list不斷重試。如果某臺機器發(fā)生了臨時性異常,將數(shù)據(jù)寫入后續(xù)的備用機器并在備用機器中記錄臨時異常的機器信息。對于讀請求,根據(jù)DHT算法計算出數(shù)據(jù)所屬節(jié)點后根據(jù)負載策略選擇R個節(jié)點,從中讀取R份數(shù)據(jù),如果數(shù)據(jù)一致,直接返回客戶端;如果數(shù)據(jù)不一致,采用vector clock的方法解決沖突。Dynamo系統(tǒng)默認的策略是選擇最新的數(shù)據(jù),當(dāng)然用戶也可以自定義沖突處理方法。每個寫入系統(tǒng)的<key, value>對都記錄一個vector lock信息,vector lock就是一系列<機器節(jié)點號, 版本號/時間戳>對,記錄每臺機器對該數(shù)據(jù)的最新更新版本信息。如下圖:


          讀取時進行沖突解決,如果一臺機器讀到的數(shù)據(jù)的vector lock記錄的所有版本信息都小于另一臺機器,直接返回vector lock較大的數(shù)據(jù);如果二者是平行版本,根據(jù)時間戳選擇最新的數(shù)據(jù)或者通過用戶自定義策略解決沖突。讀請求除了返回數(shù)據(jù)<key, value>值以外還返回vector lock信息,后續(xù)的寫操作需要帶上該信息。

          問題1:垃圾數(shù)據(jù)如何回收?

          Dynamo的垃圾回收機制主要依賴每個節(jié)點上的存儲引擎,如Berkely db存儲引擎,merge-dump存儲引擎等。其它操作,如Merkle Tree同步產(chǎn)生的垃圾文件回收可以和底層存儲引擎配合完成。

          問題2:Dynamo有沒有可能丟數(shù)據(jù)?

          關(guān)鍵在于K, W, R的設(shè)置。假設(shè)一個讀敏感應(yīng)用設(shè)置K=3, W=3, R=1,待處理的數(shù)據(jù)原本屬于節(jié)點A, B, C,節(jié)點B出現(xiàn)臨時性故障的過程中由節(jié)點D代替。在節(jié)點B出現(xiàn)故障到節(jié)點B同步完成節(jié)點D暫存的修改這段時間內(nèi),如果讀請求落入節(jié)點B或者D都將出現(xiàn)丟數(shù)據(jù)的問題。這里需要適當(dāng)處理下,對于B節(jié)點下線的情況,由于其它機器要么緩存了B節(jié)點已下線信息,要么讀取時將發(fā)現(xiàn)B節(jié)點處于下線狀態(tài),這是只需要將請求轉(zhuǎn)發(fā)其它節(jié)點即可;對于B節(jié)點上線情況,可以等到B節(jié)點完全同步以后才開始提供讀服務(wù)。對于設(shè)置W<K的應(yīng)用,Dynamo讀取時需要解決沖突,可能丟數(shù)據(jù)??傊珼ynamo中可以保證讀取的機器都是有效的(處于正常服務(wù)狀態(tài)),但W != K時不保證所有的有效機器均同步了所有更新操作。

          問題3:Dynamo的寫入數(shù)據(jù)有沒有順序問題?

          假設(shè)要寫入兩條數(shù)據(jù)"add item"和"delete item",如果寫入的順序不同,將導(dǎo)致完全不同的結(jié)果。如果設(shè)置W=K,對于同一個客戶端,由于寫入所有的機器以后才返回,可以保證順序;而多個客戶端的寫操作可能被不同的節(jié)點處理,不能保證順序性。如果設(shè)置W < K,Dynamo不保證順序性。

          問題4:沖突解決后是否需要將結(jié)果值更新存儲節(jié)點?

          讀操作解決沖突后不需要將結(jié)果值更新存儲節(jié)點。產(chǎn)生沖突的情況一般有機器下線或者多個客戶端導(dǎo)致的順序問題。機器下線時retry_list中的操作將丟失,某些節(jié)點不能獲取所有的更新操作。對于機器暫時性或者永久性的異常,Dynamo中內(nèi)部都有同步機制進行處理,但是對于retry_list中的操作丟失或者多個客戶端引發(fā)的順序問題,Dynamo內(nèi)部根本無法分辨數(shù)據(jù)是否正確。唯一的沖突解決機器在讀操作,Dynamo可以設(shè)計成讀操作將沖突解決結(jié)果值更新存儲節(jié)點,但是這樣會使讀操作變得復(fù)雜和不高效。所以,比較好的做法是每個寫操作都帶上讀操作返回的多個版本數(shù)據(jù),寫操作將沖突處理的結(jié)果更新存儲節(jié)點。

          posted @ 2009-12-04 23:05 Programmers 閱讀(1062) | 評論 (0)編輯 收藏
          分布式系統(tǒng)或其它論文里面經(jīng)常出現(xiàn)下面幾個名詞:
          樂觀鎖:有時稱作optimistic concurrency control, 指并發(fā)控制的時候“樂觀”地認為沖突的概率很小,萬一發(fā)生了沖突再重試。具體表現(xiàn)為事務(wù)執(zhí)行過程中不鎖住其它事務(wù),等到事務(wù)提交的時候看一下是否發(fā)生了沖突,如果沖突則重試或回滾,否則提交事務(wù)。
          悲觀鎖:并發(fā)控制的時候總是很悲觀,事務(wù)執(zhí)行過程中鎖住其它事務(wù),事務(wù)提交時不會有沖突。
          從表面上看,悲觀鎖比較符合計算機基礎(chǔ)課上灌輸?shù)乃季S,然而,在分布式系統(tǒng)環(huán)境下,異常是常有的事。假設(shè)分布式系統(tǒng)采用悲觀鎖設(shè)計,如果客戶端發(fā)出事務(wù)(加鎖)請求后異常退出,將導(dǎo)致系統(tǒng)被永久鎖住。Web應(yīng)用存儲系統(tǒng)一般采用樂觀鎖設(shè)計,這和Web應(yīng)用的讀/寫比例一般超過10相關(guān)。系統(tǒng)設(shè)計的時候面臨這樣一種CAS(Compare-And-Swap)需求:如果待操作項符合某個條件則修改。我們可以采用悲觀鎖鎖住待操作項的所有修改,再加上鎖的最大持有時間限制,但這樣的API設(shè)計風(fēng)險很大,樂觀鎖可以很好地解決該問題。

          coarse-grained vs fine-grained:粗粒度和細粒度。J2EE中常用來指API的粒度,比如, 我有一個遠程對象, 他有很多屬性和對應(yīng)的getter和setter方法, 如果我們遠程調(diào)用對象每個屬性的getter和setter方法, 就會產(chǎn)生很多遠程方法調(diào)用. 這就是fine-grained, 會造成性能問題。所以我們可以用一個setdata或getdata的方法把一些屬性的訪問封裝起來, 只用一個遠程方法傳輸一個data transfer object來對該對象進行賦值和訪問, 這就是coarse-grained。Google Chubby中用來表示鎖的粒度。coarse-grained指的是分布式鎖的持有時間可以很長并不斷延長鎖的持有時間,這樣的好處在于對鎖服務(wù)器的壓力較小,難點在于鎖服務(wù)端宕機恢復(fù)需要恢復(fù)鎖的狀態(tài),find-grained指的是分布式鎖的持有時間一般是秒級或者毫秒級,這樣的好處在于鎖服務(wù)器宕機恢復(fù)不必維持原有鎖的狀態(tài),但這種簡單的設(shè)計方法導(dǎo)致服務(wù)器壓力很大,不容易擴展到大集群。Google的設(shè)計一開始就把集群的線性擴展放到了一個很重要的位置,所以Google Chubby里面使用了coarse-grained的設(shè)計??蛻舳丝梢院唵蔚卦赾oarse-grained鎖的基礎(chǔ)上擴展出一個fine-grained的鎖,具體請看Chubby論文:scholar.google.cn/scholar
          posted @ 2009-12-03 14:58 Programmers 閱讀(528) | 評論 (0)編輯 收藏
          Google在SIGMOD 2008上透露了Megastore部分實現(xiàn)細節(jié),詳情參考大牛James Hamilton的blog:perspectives.mvdirona.com/2008/07/10/GoogleMegastore.aspx
          大牛的文章固然不錯,不過肯定不大好懂,下面我說一下我對文章的翻譯+理解:
          1. Google Bigtable只支持最簡單的insert, update, del, ...等函數(shù)調(diào)用API,不支持SQL形式的API,這個轉(zhuǎn)換工作放到了Megastore層次上來做。SQL對于異步Bigtable調(diào)用的支持需要仔細考慮。
          2. 對于索引支持文章中已經(jīng)說得很明顯了,維護一個<索引,row_key>的索引表,更新時先更新數(shù)據(jù)表再更新索引表,索引項越多,更新效率越低,但是讀基本不怎么影響,特別適合互聯(lián)網(wǎng)這種讀/寫比例一般超過10倍的應(yīng)用。
          3. Megastore不提供通用的分布式事務(wù)支持,分布式事務(wù)僅僅限于同一個entity group。Bigtable支持單行的事務(wù),而Megastore支持row key前綴相同的多行事務(wù),如一個用戶的blog, post, photo,可以將它們存在到Bigtable的一張表中,row key為user_id + blog_id + post_id + photo_id,這樣同一個user的數(shù)據(jù)即為一個entity group。然而,這樣就導(dǎo)致不能支持像百付寶、支付寶等電子商務(wù)轉(zhuǎn)賬事務(wù),我暫時也還不清楚支持同一個entity group內(nèi)部的事務(wù)意義有多大,即有多少web應(yīng)用需要這種同一個entity group下的事務(wù)支持。
          4. Megastore支持事務(wù)的方式當(dāng)然還是傳統(tǒng)的Two-phase commit協(xié)議,為了解決這個協(xié)議中協(xié)調(diào)者失效導(dǎo)致的問題,引入Paxos協(xié)議(Google Chubby)使協(xié)調(diào)者不再成為單點。具體做起來會非常復(fù)雜,這里提供超級大牛Jim Gray和Lamport的一篇論文供大家參考:scholar.google.com/scholar   個人認為Oracle的事務(wù)內(nèi)部是一個基本的Two-phase commit協(xié)議,協(xié)調(diào)者宕機時由Oracle DBA手工介入,由于其復(fù)雜性,對DBA要求很高,所以Taobao一直網(wǎng)羅國內(nèi)頂級DBA牛人。
          5. Megastore具體事務(wù)實現(xiàn)時會借用Bigtable 原有的機制來實現(xiàn)commit log, replication等功能。可能的實現(xiàn)為:建一張專門的Entity group root表,加載Entity group root表的Tablet Server做為協(xié)調(diào)者角色進行分布式事務(wù)控制。然而問題在于加載Entity group root表的Tablet Server是一個單點,實現(xiàn)多個Tablet Server服務(wù)同一個Bigtable Tablet又是一件極其困難的事情。
          6. Megastore不支持復(fù)雜的Join操作,這和互聯(lián)網(wǎng)公司應(yīng)用性質(zhì)相關(guān)。Join操作一般不要求強一致性,可以通過多表冗余方式實現(xiàn)。
          7. 事務(wù)的并發(fā)控制采用最優(yōu)控制策略。簡單來說,就是事務(wù)過程中不要鎖住其它事務(wù)操作,提交的時候看一下是否與其它事務(wù)沖突,如果有沖突則重試。Megastore實現(xiàn)時沒有rollback,失敗了都是retry,宕機了就回放操作日志。
          8. Megastore/Bigtable的實現(xiàn)者認為讓用戶自己指定entity group, locality group是合理的(和數(shù)據(jù)存儲位置相關(guān))。這樣的效果是同一個entity group的數(shù)據(jù)經(jīng)常存放在一臺機器上,分布式事務(wù)的性能損耗較小,這也就說明在分布式系統(tǒng)中,沒有代價的scalable是不存在的,要想獲得scalable和性能,就必須犧牲關(guān)系數(shù)據(jù)庫的一些特性及用戶的易用性。

          上述均為個人的粗淺看法,如何避免協(xié)調(diào)者的單點等很多問題還沒有想清楚,Bigtable和Megastore的replication策略看起來也有些沖突,想清楚后將續(xù)寫!
          posted @ 2009-12-03 14:58 Programmers 閱讀(616) | 評論 (0)編輯 收藏
          前文說到,Dynamo DHT能夠定位數(shù)據(jù)所屬的節(jié)點,為了處理節(jié)點失效的情況(DHT環(huán)中刪除節(jié)點),需要對節(jié)點的數(shù)據(jù)進行replication。思路如下:假設(shè)數(shù)據(jù)存儲K份,DHT定位到的數(shù)據(jù)所屬節(jié)點為N,則數(shù)據(jù)存儲在節(jié)點N, N+1, ..., N+K-1上。如果第i (0 <= i <= K-1) 臺機器宕機,則往后找一臺機器N+K臨時替代。臨時替代的機器定時ping機器N+i,等到它重啟后將這些臨時數(shù)據(jù)重新寫入N+i。機器N+i宕機的這段時間內(nèi),所有的讀寫均落入到機器[N, N+i-1]和[N+i+1, N+K]中,這段時間會出現(xiàn)數(shù)據(jù)一致性問題,需要引入專門的沖突解決協(xié)議,在Dynamo中是通過Lamport的vector clock實現(xiàn)的。如果機器N+i永久失效,機器N+K需要進行同步操作。一般來說,從機器N+i宕機開始到被認定為永久失效的時間不會太長,積累的寫操作也不會太多,可以采用Merkle Tree對機器的數(shù)據(jù)文件進行快速同步。
          為了在可用性和效率之間權(quán)衡,Dynamo的設(shè)計中允許用戶指定讀/寫個數(shù)R和W值。R和W分別表示每個讀/寫操作需要操作的副本數(shù)。只要滿足R+W > K,就可以保證在存在不超過一臺機器故障的時候,至少能夠讀到一份有效的數(shù)據(jù)。如果應(yīng)用重視讀效率,可以設(shè)置W = K, R = 1;如果應(yīng)用需要在讀/寫之間權(quán)衡,一般可設(shè)置W = 2, R = 2,K = 3。

          問題1:Dynamo中如何解決網(wǎng)絡(luò)分區(qū)問題?
          前面已經(jīng)提到,DHT協(xié)議本身是無法處理網(wǎng)絡(luò)分區(qū)的。在Dynamo中,引入種子節(jié)點,服務(wù)器定期向種子節(jié)點輪詢整個機群的機器信息,種子節(jié)點的選擇符合一定的策略使得網(wǎng)絡(luò)分區(qū)問題出現(xiàn)概率降至工程可以接受的水平。

          問題2:如何將數(shù)據(jù)復(fù)制到多個數(shù)據(jù)中心?
          每份數(shù)據(jù)都被復(fù)制到N, N+1, ..., N+K-1這K臺機器中,為了保證這些機器屬于不同的數(shù)據(jù)中心,需要合理地設(shè)計獲取數(shù)據(jù)節(jié)點號的Hash算法。當(dāng)然,Dynamo通過直接手工配置每臺機器的編號解決??雌饋砗苌秸?,不過很實用,呵呵。 閱讀全文
          類別:默認分類 查看評論
          文章來源:http://hi.baidu.com/knuthocean/blog/item/f085d72a06d4ee27d52af170.html
          posted @ 2009-12-03 13:43 Programmers 閱讀(331) | 評論 (0)編輯 收藏
          DHT全稱Distributed Hash Table (en.wikipedia.org/wiki/Distributed_hash_table),在P2P系統(tǒng)中經(jīng)常用來定位數(shù)據(jù)所屬機器。這就涉及到一致哈希(consistent hashing)思想,分布式系統(tǒng)中經(jīng)常出現(xiàn)機器上下線,如果采用通常的Hash方法來查找數(shù)據(jù)所屬機器,機器上下線將導(dǎo)致整個集群的數(shù)據(jù)分布被打亂。這是因為,機器上下線將導(dǎo)致機器序號及Hash函數(shù)的改變,一致哈希做了簡單調(diào)整:每臺機器存儲哈希值和它最為接近的數(shù)據(jù)。在Chord系統(tǒng)中,順時針到達的第一臺機器即為最近的機器。
          外部的數(shù)據(jù)可能首先傳輸至集群中的任意一臺機器,為了找到數(shù)據(jù)所屬機器,要求每臺機器維護一定的集群機器信息用于定位。最直觀的想法當(dāng)然是每臺機器分別維護它的前一臺及后一臺機器的信息,機器的編號可以為機器IP的Hash值,定位機器最壞情況下復(fù)雜度為O(N)??梢圆捎闷胶饣枷雭韮?yōu)化(如同平衡二叉樹優(yōu)化數(shù)組/鏈表),使每一臺機器存儲O(logN)的集群機器信息,定位機器最壞情況下復(fù)雜度為O(logN)。
          首先考慮每臺機器維護前一臺及后一臺機器信息的情況,這里的問題是機器上下線導(dǎo)致緩存信息的不一致,我們需要設(shè)計協(xié)議使得在確定一段比較短的時間內(nèi)能夠糾正這種錯誤。對于新機器加入,首先進行一次查找操作找到該機器的下一臺機器,并記錄下一臺機器的信息。機器內(nèi)的每臺機器都定時向它的后繼發(fā)送心跳信息,如果后繼記錄的前一臺機器編號在二者之間,說明有新機器加入,這時需要更新后一臺機器編號為新加入編號;收到心跳信息的后繼也需要檢查,如果發(fā)送心跳的機器編號較為接近則更新為前一臺機器。機器下線將導(dǎo)致機器循環(huán)鏈表斷開,所以,每臺機器都維護了R個(一般取R值為3)最近的后繼信息,發(fā)現(xiàn)后繼節(jié)點下線時將通知其它后繼節(jié)點并加入新的替換節(jié)點。如果R個后繼節(jié)點同時下線,需要操作人員手工介入修復(fù)循環(huán)鏈。
          Chord中的每臺機器維護O(logN)的機器信息是一種空間換時間的做法,實現(xiàn)時需要引入額外的消息交換協(xié)議。這種做法依賴于如下前提:每臺機器維護的前一臺機器及后一臺機器除了短時間不一致外總是正確的。

          問題1:機器緩存短時間不一致有什么影響?數(shù)據(jù)正確性依靠什么保證?
          短時間可能出現(xiàn)緩存的機器信息不正確的情況。比如有A, C, D, E四臺機器,再加入一臺機器B,機器加入的過程中,原本屬于B的數(shù)據(jù)可能寫入到B或者C,這都是允許的。又如刪除機器C,訪問機器C的節(jié)點得不到數(shù)據(jù)。數(shù)據(jù)的可用性及一致性還需要通過額外的replication及沖突處理協(xié)議解決。
          問題2:DHT能否處理網(wǎng)絡(luò)分區(qū)問題?
          DHT不能處理網(wǎng)絡(luò)分區(qū)問題,理論上存在整個DHT被分成多個子集的情況。我想,這時侯需要外部的機制介入,如維護一臺外部機器保存所有機器列表等。 閱讀全文
          類別:默認分類 查看評論
          文章來源:http://hi.baidu.com/knuthocean/blog/item/cca1e711221dcfcca6ef3f1d.html
          posted @ 2009-12-03 13:43 Programmers 閱讀(416) | 評論 (0)編輯 收藏
          Amazon Dynamo是組合使用P2P各種技術(shù)的經(jīng)典論文,對單機key-value存儲系統(tǒng)擴展成分布式系統(tǒng)有借鑒意義,值得仔細推敲。本人準(zhǔn)備近期深入閱讀該論文,并寫下讀書筆記自娛自樂。當(dāng)然,如果有志同道合的同學(xué)非常歡迎交流。以下是閱讀計劃:
          1. 一切從DHT開始。Dynamo首先要解決的就是給定關(guān)鍵字key找出服務(wù)節(jié)點的問題。Dynamo的思想與Chord有些類似,我們可以拋開replication問題,看看Chord和Dynamo是如何通過應(yīng)用DHT解決服務(wù)節(jié)點定位問題的。這里面的難點當(dāng)然是節(jié)點加入和刪除,尤其是多個節(jié)點并發(fā)加入/刪除。建議預(yù)先閱讀Chord論文:scholar.google.com/scholar 。
          2. Dynamo的replication。理解了DHT,我們需要結(jié)合replication理解服務(wù)節(jié)點定位及錯誤處理等問題。
          3. Dynamo錯誤處理。這里包括兩種類型的錯誤,一種是暫時性的,如由于程序bug core dump后重啟,另外一種是永久性的,這里用到了Merkle Tree同步技術(shù)。
          4. Dynamo讀/寫流程設(shè)計及沖突解決。這里主要涉及到一致性模型。Dynamo允許根據(jù)應(yīng)用配置R和W值來權(quán)衡效率及Availability,并使用了Lamport的Vector Clock來解決沖突。
          5. Dynamo優(yōu)化。主要是Load rebalance的優(yōu)化。
          6. Dynamo實現(xiàn)。如果讓我們自己來實現(xiàn)Dynamo,我們應(yīng)該如何劃分模塊以及實現(xiàn)過程中有哪些關(guān)鍵問題?
          后續(xù)將按照計劃對每個問題做閱讀筆記 :) 閱讀全文
          類別:默認分類 查看評論
          文章來源:http://hi.baidu.com/knuthocean/blog/item/8838ad34f9ae1dbdd0a2d3d7.html
          posted @ 2009-12-03 13:43 Programmers 閱讀(891) | 評論 (1)編輯 收藏
          推薦兩本分布式系統(tǒng)方面書籍:
          1. <<Distributed Systems - Principles and Paradigms>> Andrew S. Tanenbaum www.china-pub.com/40777&ref=ps Tanenbaum出品,必屬精品。本書條理清晰,涉及到分布式系統(tǒng)的方方面面,通俗易懂并附錄了分布式系統(tǒng)各個經(jīng)典問題的論文閱讀資料,是分布式系統(tǒng)入門的不二選擇。感覺和以前看過的<<Introduction to Algorithm>>一樣,讀起來讓人心曠神怡,建議通讀。
          2. <<Introduction to Distributed Algorithms>> Gerard Tel www.china-pub.com/13102&ref=ps 我們老大推薦的書籍。雖然從名字看是入門型書籍,不過內(nèi)容一點都不好懂,適合有一定基礎(chǔ)的同學(xué)。另外,千萬要注意,一定要買英文原版。 閱讀全文
          類別:默認分類 查看評論
          文章來源:http://hi.baidu.com/knuthocean/blog/item/8838ad34fbfb1fbdd1a2d364.html
          posted @ 2009-12-03 13:43 Programmers 閱讀(1215) | 評論 (0)編輯 收藏
          僅列出標(biāo)題  下一頁
          主站蜘蛛池模板: 万荣县| 颍上县| 五寨县| 巴青县| 广元市| 博罗县| 泗阳县| 泰和县| 彭水| 泰兴市| 句容市| 利津县| 汕尾市| 华蓥市| 尚义县| 隆尧县| 玉田县| 建宁县| 张北县| 新绛县| 错那县| 祥云县| 重庆市| 郴州市| 永吉县| 马边| 翁源县| 东丰县| 盐源县| 朔州市| 阳东县| 峨边| 南安市| 正阳县| 广灵县| 漠河县| 绍兴市| 惠州市| 临桂县| 昭苏县| 延庆县|