什麼是分佈式

  • 222013-10

    簡單說,分佈式是以縮短單個任務的執行時間來提高效率的,而集羣則是經過提升單位時間內執行的任務數來提高效率。html

    例如:java

    若是一個任務由10個子任務組成,每一個子任務單獨執行需1小時,則在一臺服務器上執行改任務需10小時。mysql

    採用分佈式方案,提供10臺服務器,每臺服務器只負責處理一個子任務,不考慮子任務間的依賴關係,執行完這個任務只需一個小時。(這種工做模式的一個典型表明就是Hadoop的Map/Reduce分佈式計算模型)linux

    而採用集羣方案,一樣提供10臺服務器,每臺服務器都能獨立處理這個任務。假設有10個任務同時到達,10個服務器將同時工做,10小後,10個任務同時完成,這樣,整身來看,仍是1小時內完成一個任務!nginx

     

    如下是摘抄自網絡文章:程序員

    集羣概念

    1. 兩大關鍵特性 
    集羣是一組協同工做的服務實體,用以提供比單一服務實體更具擴展性與可用性的服務平臺。在客戶端看來,一個集羣就象是一個服務實體,但事實上集羣由一組服務實體組成。與單一服務實體相比較,集羣提供瞭如下兩個關鍵特性:web

    ·  可擴展性--集羣的性能不限於單一的服務實體,新的服務實體能夠動態地加入到集羣,從而加強集羣的性能。算法

    ·  高可用性--集羣經過服務實體冗餘使客戶端免於輕易遇到out of service的警告。在集羣中,一樣的服務能夠由多個服務實體提供。若是一個服務實體失敗了,另外一個服務實體會接管失敗的服務實體。集羣提供的從一個出 錯的服務實體恢復到另外一個服務實體的功能加強了應用的可用性。sql

    2. 兩大能力 
    爲了具備可擴展性和高可用性特色,集羣的必須具有如下兩大能力:shell

    ·  負載均衡--負載均衡能把任務比較均衡地分佈到集羣環境下的計算和網絡資源。

    ·  錯誤恢復--因爲某種緣由,執行某個任務的資源出現故障,另外一服務實體中執行同一任務的資源接着完成任務。這種因爲一個實體中的資源不能工做,另外一個實體中的資源透明的繼續完成任務的過程叫錯誤恢復。

    負載均衡和錯誤恢復都要求各服務實體中有執行同一任務的資源存在,並且對於同一任務的各個資源來講,執行任務所需的信息視圖(信息上下文)必須是同樣的。

    3. 兩大技術 
    實現集羣務必要有如下兩大技術:

    ·  集羣地址--集羣由多個服務實體組成,集羣客戶端經過訪問集羣的集羣地址獲取集羣內部各服務實體的功能。具備單一集羣地址(也叫單一影像)是集羣的一個基 本特徵。維護集羣地址的設置被稱爲負載均衡器。負載均衡器內部負責管理各個服務實體的加入和退出,外部負責集羣地址向內部服務實體地址的轉換。有的負載均 衡器實現真正的負載均衡算法,有的只支持任務的轉換。只實現任務轉換的負載均衡器適用於支持ACTIVE-STANDBY的集羣環境,在那裏,集羣中只有 一個服務實體工做,當正在工做的服務實體發生故障時,負載均衡器把後來的任務轉向另一個服務實體。

    ·  內部通訊--爲了能協同工做、實現負載均衡和錯誤恢復,集羣各實體間必須時常通訊,好比負載均衡器對服務實體心跳測試信息、服務實體間任務執行上下文信息的通訊。

    具備同一個集羣地址使得客戶端能訪問集羣提供的計算服務,一個集羣地址下隱藏了各個服務實體的內部地址,使得客戶要求的計算服務能在各個服務實體之間分佈。內部通訊是集羣能正常運轉的基礎,它使得集羣具備均衡負載和錯誤恢復的能力。

    集羣分類

    Linux集羣主要分紅三大類( 高可用集羣, 負載均衡集羣,科學計算集羣)

    高可用集羣( High Availability Cluster)
    負載均衡集羣(Load Balance Cluster)
    科學計算集羣(High Performance Computing Cluster)
    ================================================

    具體包括:

    Linux High Availability 高可用集羣                                       
    (普通兩節點雙機熱備,多節點HA集羣,RAC, shared, share-nothing集羣等)

    Linux Load Balance 負載均衡集羣                                      
     (LVS等....)

    Linux High Performance Computing 高性能科學計算集羣     
     (Beowulf 類集羣....)

    分佈式存儲                                                                         
    其餘類linux集羣              
    (如Openmosix, rendering farm 等..)

    詳細介紹

    1. 高可用集羣(High Availability Cluster)
    常見的就是2個節點作成的HA集羣,有不少通俗的不科學的名稱,好比"雙機熱備", "雙機互備", "雙機".
    高可用集羣解決的是保障用戶的應用程序持續對外提供服務的能力。 (請注意高可用集羣既不是用來保護業務數據的,保護的是用戶的業務程序對外不間斷提供服務,把因軟件/硬件/人爲形成的故障對業務的影響下降到最小程度)。

    2. 負載均衡集羣(Load Balance Cluster)

    負載均衡系統:集羣中全部的節點都處於活動狀態,它們分攤系統的工做負載。通常Web服務器集羣、數據庫集羣和應用服務器集羣都屬於這種類型。

    負載均衡集羣通常用於相應網絡請求的網頁服務器,數據庫服務器。這種集羣能夠在接到請求時,檢查接受請求較少,不繁忙的服務器,並把請求轉到這些服務器上。從檢查其餘服務器狀態這一點上看,負載均衡和容錯集羣很接近,不一樣之處是數量上更多。

    3. 科學計算集羣(High Performance Computing Cluster)

    高性能計算(High Perfermance Computing)集羣,簡稱HPC集羣。這類集羣致力於提供單個計算機所不能提供的強大的計算能力。

    高性能計算分類  
     高吞吐計算(High-throughput Computing)
      有一類高性能計算,能夠把它分紅若干能夠並行的子任務,並且各個子任務彼此間沒有什麼關聯。象在家搜尋外星人( SETI@HOME  -- Search for Extraterrestrial Intelligence at Home )就是這一類型應用。這一項目是利用Internet上的閒置的計算資源來搜尋外星人。SETI項目的服務器將一組數據和數據模式發給Internet上 參加SETI的計算節點,計算節點在給定的數據上用給定的模式進行搜索,而後將搜索的結果發給服務器。服務器負責將從各個計算節點返回的數據聚集成完整的 數據。由於這種類型應用的一個共同特徵是在海量數據上搜索某些模式,因此把這類計算稱爲高吞吐計算。所謂的Internet計算都屬於這一類。按照 Flynn的分類,高吞吐計算屬於SIMD(Single Instruction/Multiple Data)的範疇。

     分佈計算(Distributed Computing)
      另外一類計算恰好和高吞吐計算相反,它們雖然能夠給分紅若干並行的子任務,可是子任務間聯繫很緊密,須要大量的數據交換。按照Flynn的分類,分佈式的高性能計算屬於MIMD(Multiple Instruction/Multiple Data)的範疇。

    4. 分佈式(集羣)與集羣的聯繫與區別 
    分佈式是指將不一樣的業務分佈在不一樣的地方。 
    而集羣指的是將幾臺服務器集中在一塊兒,實現同一業務。 
    分佈式中的每個節點,均可以作集羣。 
    而集羣並不必定就是分佈式的。 
    舉例:就好比新浪網,訪問的人多了,他能夠作一個羣集,前面放一個響應服務器,後面幾臺服務器完成同一業務,若是有業務訪問的時候,響應服務器看哪臺服務器的負載不是很重,就將給哪一臺去完成。 
    而分佈式,從窄意上理解,也跟集羣差很少, 可是它的組織比較鬆散,不像集羣,有一個組織性,一臺服務器垮了,其它的服務器能夠頂上來。 
    分佈式的每個節點,都完成不一樣的業務,一個節點垮了,哪這個業務就不可訪問了。

    發佈於 2個月前, 閱讀(16) | 評論(0) | 投票(0) | 收藏(0)  閱讀全文...
  • 162013-10

    一致性hash和solr千萬級數據分佈式搜索引擎中的應用

    互聯網創業中大部分人都是草根創業,這個時候沒有強勁的服務器,也沒有錢去買很昂貴的海量數據庫。在這樣嚴峻的條件下,一批又一批的創業者從創業中得到成功,這個和當前的開源技術、海量數據架構有着必不可分的關係。好比咱們使用mysql、nginx等開源軟件,經過架構和低成本服務器也能夠搭建千萬級用戶訪問量的系統。新浪微博、淘寶網、騰訊等大型互聯網公司都使用了不少開源免費系統搭建了他們的平臺。因此,用什麼不要緊,只要可以在合理的狀況下采用合理的解決方案。

    那怎麼搭建一個好的系統架構呢?這個話題太大,這裏主要說一下數據分流的方式。好比咱們的數據庫服務器只能存儲200個數據,忽然要搞一個活動預估達到600個數據。
    能夠採用兩種方式:橫向擴展或者縱向擴展。
    縱向擴展是升級服務器的硬件資源。可是隨着機器的性能配置越高,價格越高,這個代價對於通常的小公司是承擔不起的。
    橫向擴展是採用多個廉價的機器提供服務。這樣一個機器只能處理200個數據、3個機器就能夠處理600個數據了,若是之後業務量增長還能夠快速配置增長。在大多數狀況都選擇橫向擴展的方式。以下圖:
    圖1

    圖2

    如今有個問題了,這600個數據如何路由到對應的機器。須要考慮若是均衡分配,假設咱們600個數據都是統一的自增id數據,從1~600,分紅3堆能夠採用 id mod 3的方式。其實在真實環境可能不是這種id是字符串。須要把字符串轉變爲hashcode再進行取模。

    目前看起來是否是解決咱們的問題了,全部數據都很好的分發而且沒有達到系統的負載。但若是咱們的數據須要存儲、須要讀取就沒有這麼容易了。業務增多怎麼辦,你們按照上面的橫向擴展知道須要增長一臺服務器。可是就是由於增長這一臺服務器帶來了一些問題。看下面這個例子,一共9個數,須要放到2臺機器(一、2)上。各個機器存放爲:1號機器存放一、三、五、七、9 ,2號機器存放 二、四、六、8。若是擴展一臺機器3如何,數據就要發生大遷移,1號機器存放一、四、7, 2號機器存放二、五、8, 3號機器存放三、六、9。如圖:

    圖3
    從圖中能夠看出 1號機器的三、五、9遷移出去了、2好機器的四、6遷移出去了,按照新的秩序再從新分配了一遍。數據量小的話從新分配一遍代價並不大,但若是咱們擁有上億、上T級的數據這個操做成本是至關的高,少則幾個小時多則數天。而且遷移的時候原數據庫機器負載比較高,那你們就有疑問了,是否是這種水平擴展的架構方式不太合理?

    —————————–華麗分割線—————————————

    一致性hash就是在這種應用背景提出來的,如今被普遍應用於分佈式緩存,好比memcached。下面簡單介紹下一致性hash的基本原理。最先的版本 http://dl.acm.org/citation.cfm?id=258660。國內網上有不少文章都寫的比較好。如: http://blog.csdn.net/x15594/article/details/6270242

    下面簡單舉個例子來講明一致性hash。

    準備:一、二、3 三臺機器
    還有待分配的9個數 一、二、三、四、五、六、七、八、9
    一致性hash算法架構

    步驟
    1、構造出來 2的32次方 個虛擬節點出來,由於計算機裏面是01的世界,進行劃分時採用2的次方數據容易分配均衡。另 2的32次方是42億,咱們就算有超大量的服務器也不可能超過42億臺吧,擴展和均衡性都保證了。
    一致性hash
    2、將三臺機器分別取IP進行hashcode計算(這裏也能夠取hostname,只要可以惟一區別各個機器就能夠了),而後映射到2的32次方上去。好比1號機器算出來的hashcode而且mod (2^32)爲 123(這個是虛構的),2號機器算出來的值爲 2300420,3號機器算出來爲 90203920。這樣三臺機器就映射到了這個虛擬的42億環形結構的節點上了。
    圖5
    3、將數據(1-9)也用一樣的方法算出hashcode並對42億取模將其配置到環形節點上。假設這幾個節點算出來的值爲 1:10,2:23564,3:57,4:6984,5:5689632,6:86546845,7:122,8:3300689,9:135468。能夠看出 一、三、7小於123, 二、四、9 小於 2300420 大於 123, 五、六、8 大於 2300420 小於90203920。從數據映射到的位置開始順時針查找,將數據保存到找到的第一個Cache節點上。若是超過2^32仍然找不到Cache節點,就會保存到第一個Cache節點上。也就是一、三、7將分配到1號機器,二、四、9將分配到2號機器,五、六、8將分配到3號機器。
    圖6
    這個時候你們可能會問,我到如今沒有看見一致性hash帶來任何好處,比傳統的取模還增長了複雜度。如今立刻來作一些關鍵性的處理,好比咱們增長一臺機器。按照原來咱們須要把全部的數據從新分配到四臺機器。一致性hash怎麼作呢?如今4號機器加進來,他的hash值算出來取模後是12302012。 五、8 大於2300420 小於12302012 ,6 大於 12302012 小於90203920 。這樣調整的只是把五、8從3號機器刪除,4號機器中加入 五、6。
    圖7
    同理,刪除機器怎麼作呢,假設2號機器掛掉,受影響的也只是2號機器上的數據被遷移到離它節點,上圖爲4號機器。
    圖8
    你們應該明白一致性hash的基本原理了吧。不過這種算法仍是有缺陷,好比在機器節點比較少、數據量大的時候,數據的分佈可能不是很均衡,就會致使其中一臺服務器的數據比其餘機器多不少。爲了解決這個問題,須要引入虛擬服務器節點的機制。如咱們一共有隻有三臺機器,一、二、3。可是實際又不可能有這麼多機器怎麼解決呢?把 這些機器各自虛擬化出來3臺機器,也就是 1a 1b 1c 2a 2b 2c 3a 3b 3c,這樣就變成了9臺機器。實際 1a 1b 1c 仍是對應1。可是實際分佈到環形節點就變成了9臺機器。數據分佈也就可以更分散一點。如圖:
    圖91

    寫了這麼多一致性hash,這個和分佈式搜索有什麼半點關係?咱們如今使用solr4搭建了分佈式搜索,測試了基於solrcloud的分佈式平臺提交20條數據竟然須要幾十秒,因此就廢棄了solrcloud。採用本身hack solr平臺,不用zookeeper作分佈式一致性管理平臺,本身管理數據的分發機制。既然須要本身管理數據的分發,就須要考慮到索引的建立,索引的更新。這樣咱們的一致性hash也就用上了。總體架構以下圖:

    圖10
    創建和更新須要維持機器的位置,可以根據數據的key找到對應的數據分發並更新。這裏須要考慮的是如何高效、可靠的把數據創建、更新到索引裏。
    備份服務器防止創建服務器掛掉,能夠根據備份服務器快速恢復。
    讀服務器主要作讀寫分離使用,防止寫索引影響查詢數據。
    集羣管理服務器管理整個集羣內的服務器狀態、告警。

    整個集羣隨着業務增多還能夠按照數據的類型劃分,好比用戶、微博等。每一個類型按照上圖架構搭建,就能夠知足通常性能的分佈式搜索。對於solr和分佈式搜索的話題後續再聊。

    擴展閱讀:
    java的hashmap隨着數據量的增長也會出現map調整的問題,必要的時候就初始化足夠大的size以防止容量不足對已有數據進行從新hash計算。

    疫苗:Java HashMap的死循環 http://coolshell.cn/articles/9606.html
    一致性哈希算法的優化—-關於如何保正在環中增長新節點時,命中率不受影響 (原拍拍同事scott)http://scottina.iteye.com/blog/650380

    語言實現:
    http://weblogs.java.net/blog/2007/11/27/consistent-hashing java 版本的例子
    http://blog.csdn.net/mayongzhan/archive/2009/06/25/4298834.aspx PHP 版的例子
    http://www.codeproject.com/KB/recipes/lib-conhash.aspx C語言版本例子

    發佈於 3個月前, 閱讀(150) | 評論(1) | 投票(0) | 收藏(21)  閱讀全文...
  • 162013-10

    1)首先在${tomcat目錄}/conf/Catalina/localhost 建立兩個solr的配置文件。

       能夠命名爲solr.xml(主服務器配置)內容爲:

     <Context docBase="F:/apache-solr-1.4.0/dist/apache-solr-1.4.0.war" reloadable="true" >  
         <Environment name="solr/home" type="java.lang.String" value="F:/apache-solr-1.4.0/example/solr" override="true" />  
     </Context> 

    slaver_solr.xml (從服務器配置)內容爲:

     <Context docBase="F:/apache-solr-1.4.0/dist/apache-solr-1.4.0.war" reloadable="true" >  
         <Environment name="solr/home" type="java.lang.String" value="F:/solr分佈式/solr" override="true" />  
     </Context> 

     

    能夠看到兩個配置所引用的後臺管理是同一個目錄的,但這個不要緊,只要solr/home的不同就好了,接着看主從服務器上solr/home的配置有什麼不同。主要是在solr/home/conf/solrconfig.xml上配置不同的,其它配置能夠互相拷貝。

     

    主要不一樣的地方爲以下:

     

    從服務器的配置

     

    <requestHandler name="/replication" class="solr.ReplicationHandler" >
        <lst name="slave">

    <!--主服務器的url-->


          <str name="masterUrl">http://localhost:8080/solr/replication</str>

    <!--定時去請求主服務器,查看索引是否有改變-->
          <str name="pollInterval">00:00:60</str>
        </lst>
    </requestHandler>

     

    主服務器的配置

     


    <requestHandler name="/replication" class="solr.ReplicationHandler" >
        <lst name="master">
          <str name="replicateAfter">commit</str>
          <str name="replicateAfter">startup</str>
          <str name="confFiles">schema.xml,stopwords.txt</str>
        </lst>

    </requestHandler>

     

    大概這樣的。啓動 tomcat看看吧。。主服務器創建索引後,從服務器會請求將索引拷貝到從服務器中。

    發佈於 3個月前, 閱讀(54) | 評論(0) | 投票(0) | 收藏(0)  閱讀全文...
  • 162013-04
    時間過得很快,來淘寶已經兩個月了,在這兩個月的時間裏,本身也感覺頗深。下面就結合淘寶目前的一些底層技術框架以及本身的一些感觸來講說如何構建一個可伸縮,高性能,高可用性的分佈式互聯網應用。

      一應用無狀態淘寶session框架

      俗話說,一個系統的伸縮性的好壞取決於應用的狀態如何管理。爲何這麼說呢?我們試想一下,假如咱們在session中保存了大量與客戶端的狀態信息的話,那麼當保存狀態信息的server宕機的時候,咱們怎麼辦?一般來講,咱們都是經過集羣來解決這個問題,而一般所說的集羣,不只有負載均衡,更重要的是要有失效恢復failover,好比tomcat採用的集羣節點廣播複製,jboss採用的配對複製等session狀態複製策略,可是集羣中的狀態恢復也有其缺點,那就是嚴重影響了系統的伸縮性,系統不能經過增長更多的機器來達到良好的水平伸縮,由於集羣節點間session的通訊會隨着節點的增多而開銷增大,所以要想作到應用自己的伸縮性,咱們須要保證應用的無狀態性,這樣集羣中的各個節點來講都是相同的,從而是的系統更好的水平伸縮。

      OK,上面說了無狀態的重要性,那麼具體如何實現無狀態呢?此時一個session框架就會發揮做用了。幸運的是淘寶已經具備了此類框架。淘寶的session框架採用的是client cookie實現,主要將狀態保存到了cookie裏面,這樣就使得應用節點自己不須要保存任何狀態信息,這樣在系統用戶變多的時候,就能夠經過增長更多的應用節點來達到水平擴展的目的.可是採用客戶端cookie的方式來保存狀態也會遇到限制,好比每一個cookie通常不能超過4K的大小,同時不少瀏覽器都限制一個站點最多保存20個cookie.淘寶cookie框架採用的是「多值cookie」,就是一個組合鍵對應多個cookie的值,這樣不只能夠防止cookie數量超過20,同時還節省了cookie存儲有效信息的空間,由於默認每一個cookie都會有大約50個字節的元信息來描述cookie。

      除了淘寶目前的session框架的實現方式之外,其實集中式session管理來完成,說具體點就是多個無狀態的應用節點鏈接一個session服務器,session服務器將session保存到緩存中,session服務器後端再配有底層持久性數據源,好比數據庫,文件系統等等。

      二有效使用緩存Tair

      作互聯網應用的兄弟應該都清楚,緩存對於一個互聯網應用是多麼的重要,從瀏覽器緩存,反向代理緩存,頁面緩存,局部頁面緩存,對象緩存等等都是緩存應用的場景。

      通常來講緩存根據與應用程序的遠近程度不一樣能夠分爲:local cache和remote cache。通常系統中要麼採用local cache,要麼採用remote cache,二者混合使用的話對於local cache和remote cache的數據一致性處理會變大比較麻煩.

      在大部分狀況下,咱們所說到的緩存都是讀緩存,緩存還有另一個類型:寫緩存.對於一些讀寫比不高,同時對數據安全性需求不高的數據,咱們能夠將其緩存起來從而減小對底層數據庫的訪問,好比統計商品的訪問次數,統計API的調用量等等,能夠採用先寫內存緩存而後延遲持久化到數據庫,這樣能夠大大減小對數據庫的寫壓力。

      OK,我以店鋪線的系統爲例,在用戶瀏覽店鋪的時候,好比店鋪介紹,店鋪交流區頁,店鋪服務條款頁面,店鋪試衣間頁面,以及店鋪內搜索界面這些界面更新不是很是頻繁,所以適合放到緩存中,這樣能夠大大減低DB的負載。另外寶貝詳情頁面相對也更新比較少,所以也適合放到緩存中來減低DB負載。

      三應用拆分HSF

      首先,在說明應用拆分以前,咱們先來回顧一下一個系統從小變大的過程當中遇到的一些問題,經過這些問題咱們會發現拆分對於構建一個大型系統是如何的重要。

      系統剛上線初期,用戶數並很少,全部的邏輯也許都是放在一個系統中的,全部邏輯跑到一個進程或者一個應用當中,這個時候由於比較用戶少,系統訪問量低,所以將所有的邏輯都放在一個應用何嘗不可。可是,兄弟們都清楚,好景不長,隨着系統用戶的不斷增長,系統的訪問壓力愈來愈多,同時隨着系統發展,爲了知足用戶的需求,原有的系統須要增長新的功能進來,系統變得愈來愈複雜的時候,咱們會發現系統變得愈來愈難維護,難擴展,同時系統伸縮性和可用性也會受到影響。那麼這個時候咱們如何解決這些問題呢?明智的辦法就是拆分這也算是一種解耦,咱們須要將原來的系統根據必定的標準,好比業務相關性等分爲不一樣的子系統,不一樣的系統負責不一樣的功能,這樣切分之後,咱們能夠對單獨的子系統進行擴展和維護,從而提升系統的擴展性和可維護性,同時咱們系統的水平伸縮性scale out大大的提高了,由於咱們能夠有針對性的對壓力大的子系統進行水平擴展而不會影響到其它的子系統,而不會像拆分之前,每次系統壓力變大的時候,咱們都須要對整個大系統進行伸縮,而這樣的成本是比較大的,另外通過切分,子系統與子系統之間的耦合減低了,當某個子系統暫時不可用的時候,總體系統仍是可用的,從而總體系統的可用性也大大加強了。

      所以一個大型的互聯網應用,確定是要通過拆分,由於只有拆分了,系統的擴展性,維護性,伸縮性,可用性纔會變的更好。可是拆分也給系統帶來了問題,就是子系統之間如何通訊的問題,而具體的通訊方式有哪些呢?通常有同步通訊和異步通訊,這裏咱們首先來講下同步通訊,下面的主題「消息系統」會說到異步通訊。既然須要通訊,這個時候一個高性能的遠程調用框架就顯得很是總要啦,所以我們淘寶也有了本身的HSF框架。

      上面所說的都是拆分的好處,可是拆分之後必然的也會帶來新的問題,除了剛纔說的子系統通訊問題外,最值得關注的問題就是系統之間的依賴關係,由於系統多了,系統的依賴關係就會變得複雜,此時就須要更好的去關注拆分標準,好比可否將一些有依賴的系統進行垂直化,使得這些系統的功能儘可能的垂直,這也是目前淘寶正在作的系統垂直化,同時必定要注意系統之間的循環依賴,若是出現循環依賴必定要當心,由於這可能致使系統連鎖啓動失敗。

      OK,既然明白了拆分的重要性,咱們看看隨着淘寶的發展,淘寶自己是如何拆分系統的。

      首先咱們來看如下這個圖:做者圖片已沒法打開,請見諒

      從上面的圖能夠看出淘寶系統的一個演變過程,在這個演變的過程當中,咱們所說的拆分就出現V2.2和V3.0之間。在V2.2版本中,淘寶幾乎全部的邏輯都放在Denali系統中,這樣致使的問題就是系統擴展和修改很是麻煩,而且更加致命的是隨着淘寶業務量的增長,若是按照V2.2的架構已經沒有辦法支撐之後淘寶的快速發展,所以你們決定對整個系統進行拆分,最終V3.0版本的淘寶系統架構圖以下:做者圖片已沒法打開,請見諒

      從上圖能夠看出V3.0版本的系統對整個系統進行了水平和垂直兩個方向的拆分,水平方向上,按照功能分爲交易,評價,用戶,商品等系統,一樣垂直方向上,劃分爲業務系統,核心業務系統以及以及基礎服務,這樣以來,各個系統均可以獨立維護和獨立的進行水平伸縮,好比交易系統能夠在不影響其它系統的狀況下獨立的進行水平伸縮以及功能擴展。

      從上面能夠看出,一個大型系統要想變得可維護,可擴展,可伸縮,咱們必須的對它進行拆分,拆分必然也帶來系統之間如何通訊以及系統之間依賴管理等問題,關於通訊方面,淘寶目前獨立開發了本身的高性能服務框架HSF,此框架主要解決了淘寶目前全部子系統之間的同步和異步通訊目前HSF主要用於同步場合,FutureTask方式的調用場景還比較少。至於系統間的依賴管理,目前淘寶還作的不夠好,這應該也是咱們之後努力解決的問題。

      四數據庫拆分TDDL

      在前面「應用拆分」主題中,咱們提到了一個大型互聯網應用須要進行良好的拆分,而那裏咱們僅僅說了」應用級別」的拆分,其實咱們的互聯網應用除了應用級別的拆分之外,還有另一個很重要的層面就是存儲如何拆分的。所以這個主題主要涉及到如何對存儲系統,一般就是所說的RDBMS進行拆分。

      好了,肯定了這個小節的主題以後,咱們回顧一下,一個互聯網應用從小變大的過程當中遇到的一些問題,經過遇到的問題來引出咱們拆分RDBMS的重要性。

      系統剛開始的時候,因系統剛上線,用戶很少,那個時候,全部的數據都放在了同一個數據庫中,這個時候由於用戶少壓力小,一個數據庫徹底能夠應付的了,可是隨着運營那些哥們辛苦的吶喊和拼命的推廣之後,忽然有一天發現,oh,god,用戶數量忽然變多了起來,隨之而來的就是數據庫這哥們受不了,它終於在某一天你們都和愜意的時候掛掉啦。此時,我們搞技術的哥們,就去看看到底是啥緣由,咱們查了查之後,發現原來是數據庫讀取壓力太大了,此時我們都清楚是到了讀寫分離的時候,這個時候咱們會配置一個server爲master節點,而後配幾個salve節點,這樣以來經過讀寫分離,使得讀取數據的壓力分攤到了不一樣的salve節點上面,系統終於又恢復了正常,開始正常運行了。可是好景仍是不長,有一天咱們發現master這哥們撐不住了,它負載老高了,汗流浹背,隨時都有翹掉的風險,這個時候就須要我們垂直分區啦也就是所謂的分庫,好比將商品信息,用戶信息,交易信息分別存儲到不一樣的數據庫中,同時還能夠針對商品信息的庫採用master,salve模式,OK,經過分庫之後,各個按照功能拆分的數據庫寫壓力被分擔到了不一樣的server上面,這樣數據庫的壓力終於有恢復到正常狀態。可是是否是這樣,咱們就能夠高枕無憂了呢?NO,這個NO,不是我說的,是前輩們經過經驗總結出來的,隨着用戶量的不斷增長,你會發現系統中的某些表會變的異常龐大,好比好友關係表,店鋪的參數配置表等,這個時候不管是寫入仍是讀取這些表的數據,對數據庫來講都是一個很耗費精力的事情,所以此時就須要咱們進行「水平分區」了這就是俗話說的分表,或者說sharding.

      OK,上面說了一大堆,無非就是告訴你們一個事實「數據庫是系統中最不容易scale out的一層」,一個大型的互聯網應用必然會通過一個從單一DB server,到Master/salve,再到垂直分區分庫,而後再到水平分區分表,sharding的過程,而在這個過程當中,Master/salve以及垂直分區相對比較容易,應用的影響也不是很大,可是分表會引發一些棘手的問題,好比不能跨越多個分區join查詢數據,如何平衡各個shards的負載等等,這個時候就須要一個通用的DAL框架來屏蔽底層數據存儲對應用邏輯的影響,使得底層數據的訪問對應用透明化。

      拿淘寶目前的狀況來講,淘寶目前也正在從昂貴的高端存儲小型機+ORACLE切換到MYSQL,切換到MYSQL之後,勢必會遇到垂直分區分庫以及水平分區Sharding的問題,所以目前淘寶根據本身的業務特色也開發了本身的TDDL框架,此框架主要解決了分庫分表對應用的透明化以及異構數據庫之間的數據複製

      五異步通訊Notify

      在」遠程調用框架」的介紹中,咱們說了一個大型的系統爲了擴展性和伸縮性方面的需求,確定是要進行拆分,可是拆分了之後,子系統之間如何通訊就成了咱們首要的問題,在」遠程調用框架」小節中,咱們說了同步通訊在一個大型分佈式系統中的應用,那麼這一小節咱們就來講說異步通訊.好了,既然說到了異步通訊,那麼」消息中間件」就要登場了,採用異步通訊這其實也是關係到系統的伸縮性,以及最大化的對各個子系統進行解耦.

      說到異步通訊,咱們須要關注的一點是這裏的異步必定是根據業務特色來的,必定是針對業務的異步,一般適合異步的場合是一些鬆耦合的通訊場合,而對於自己業務上關聯度比較大的業務系統之間,咱們仍是要採用同步通訊比較靠譜。

      OK,那麼下一步咱們說說異步能給系統帶來什麼樣子的好處。首先咱們想一想,假如系統有A和B兩個子系統構成,假如A和B是同步通訊的話,那麼要想使得系統總體伸縮性提升必須同時對A和B進行伸縮,這就影響了對整個系統進行scale out.其次,同步調用還會影響到可用性,從數學推理的角度來講,A同步調用B,若是A可用,那麼B可用,逆否命題就是若是B不可用,那麼A也不可用,這將大大影響到系統可用性,再次,系統之間異步通訊之後能夠大大提升系統的響應時間,使得每一個請求的響應時間變短,從而提升用戶體驗,所以異步在提升了系統的伸縮性以及可用性的同時,也大大的加強了請求的響應時間固然了,請求的整體處理時間也許不會變少。

      下面咱們就以淘寶的業務來看看異步在淘寶的具體應用。交易系統會與不少其它的業務系統交互,若是在一次交易過程當中採用同步調用的話,這就要求要向交易成功,必須依賴的全部系統均可用,而若是採用異步通訊之後,交易系統藉助於消息中間件Notify和其它的系統進行了解耦,這樣以來當其它的系統不可用的時候,也不會影響到某此交易,從而提升了系統的可用性。

      最後,關於異步方面的討論,我能夠推薦你們一些資源:

      1 . J2EE meets web2.0

      2. Ebay架構特色HPTS 2009

      六非結構化數據存儲 TFS,NOSQL

      在一個大型的互聯網應用當中,咱們會發現並非全部的數據都是結構化的,好比一些配置文件,一個用戶對應的動態,以及一次交易的快照等信息,這些信息通常不適合保存到RDBMS中,它們更符合一種Key-value的結構,另外還有一類數據,數據量很是的大,可是實時性要求不高,此時這些數據也須要經過另外的一種存儲方式進行存儲,另一些靜態文件,好比各個商品的圖片,商品描述等信息,這些信息由於比較大,放入RDBMS會引發讀取性能問題,從而影響到其它的數據讀取性能,所以這些信息也須要和其它信息分開存儲,而通常的互聯網應用系統都會選擇把這些信息保存到分佈式文件系統中,所以淘寶目前也開發了本身的分佈式文件系統TFS,TFS目前限制了文件大小爲2M,適合於一些小於2M數據的存放。

      隨着互聯網發展,業界從08年下半年開始逐漸流行了一個概念就是NOSQL。咱們都知道根據CAP理論,一致性,可用性和分區容錯性3者不能同時知足,最多隻能同時知足兩個,咱們傳統的關係數據採用了ACID的事務策略,而ACID的事務策略更加講究的是一種高一致性而下降了可用性的需求,可是互聯網應用每每對可用性的要求要略高於一致性的需求,這個時候咱們就須要避免採用數據的ACID事務策略,轉而採用BASE事務策略,BASE事務策略是基本可用性,事務軟狀態以及最終一致性的縮寫,經過BASE事務策略,咱們能夠經過最終一致性來提高系統的可用性,這也是目前不少NOSQL產品所採用的策略,包括facebook的cassandra,apache hbase,google bigtable等,這些產品很是適合一些非結構化的數據,好比key-value形式的數據存儲,而且這些產品有個很好的優勢就是水平伸縮性。目前淘寶也在研究和使用一些成熟的NOSQL產品。

      七監控、預警系統

      對於大型的系統來講,惟一可靠的就是系統的各個部分是不可靠。

      由於一個大型的分佈式系統中勢必會涉及到各類各樣的設備,好比網絡交換機,普通PC機,各類型號的網卡,硬盤,內存等等,而這些東東都在數量很是多的時候,出現錯誤的機率也會變大,所以咱們須要時時刻刻監控系統的狀態,而監控也有粒度的粗細之分,粒度粗一點的話,咱們須要對整個應用系統進行監控,好比目前的系統網絡流量是多少,內存利用率是多少,IO,CPU的負載是多少,服務的訪問壓力是多少,服務的響應時間是多少等這一系列的監控,而細粒度一點的話,咱們就需對好比應用中的某個功能,某個URL的訪問量是多,每一個頁面的PV是多少,頁面天天佔用的帶寬是多少,頁面渲染時間是多少,靜態資源好比圖片天天佔用的帶寬是多少等等進行進一步細粒度的監控。所以一個監控系統就變得必不可少了。

      前面說了一個監控系統的重要性,有了監控系統之後,更重要的是要和預警系統結合起來,好比當某個頁面訪問量增多的時候,系統能自動預警,某臺Server的CPU和內存佔用率忽然變大的時候,系統也能自動預警,當併發請求丟失嚴重的時候,系統也能自動預警等等,這樣以來經過監控系統和預警系統的結合能夠使得咱們能快速響應系統出現的問題,提升系統的穩定性和可用性。

      八配置統一管理

      一個大型的分佈式應用,通常都是有不少節點構成的,若是每次一個新的節點加入都要更改其它節點的配置,或者每次刪除一個節點也要更改配置的話,這樣不只不利於系統的維護和管理,同時也更加容易引入錯誤。另外不少時候集羣中的不少系統的配置都是同樣的,若是不進行統一的配置管理,就須要再全部的系統上維護一份配置,這樣會形成配置的管理維護很麻煩,而經過一個統一的配置管理能夠使得這些問題獲得很好的解決,當有新的節點加入或者刪除的時候,配置管理系統能夠通知各個節點更新配置,從而達到全部節點的配置一致性,這樣既方便也不會出錯。(編選:中國電子商務研究中心 勇全)

    發佈於 9個月前, 閱讀(89) | 評論(1) | 投票(0) | 收藏(1)  閱讀全文...
  • 262013-03

    基於HTTP協議的Web API是時下最爲流行的一種分佈式服務提供方式。不管是在大型互聯網應用仍是企業級架構中,咱們都見到了愈來愈多SOA或RESTful的Web API。爲何Web API如此流行呢?我認爲很大程度上應歸功於簡單有效的HTTP協議。HTTP協議是一種分佈式的面向資源的網絡應用層協議不管是服務器端提供Web服務,仍是客戶端消費Web服務都很是簡單。再加上瀏覽器、Javascript、AJAX、JSON以及HTML5等技術和工具的發展,互聯網應用架構設計表現出了從傳統的PHP、JSP、ASP.NET等服務器端動態網頁向Web API + RIA(富互聯網應用)過渡的趨勢。Web API專一於提供業務服務,RIA專一於用戶界面和交互設計,今後兩個領域的分工更加明晰。在這種趨勢下,Web API設計將成爲服務器端程序員的必修課。然而,正如簡單的Java語言並不意味着高質量的Java程序,簡單的HTTP協議也不意味着高質量的Web API要想設計出高質量的Web API,還須要深刻理解分佈式系統及HTTP協議的特性。

     

    冪等性定義

    本文所要探討的正是HTTP協議涉及到的一種重要性質:冪等性(Idempotence)。在HTTP/1.1規範中冪等性的定義是:

    Methods can also have the property of "idempotence" in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request.

    從定義上看,HTTP方法的冪等性是指一次和屢次請求某一個資源應該具備一樣的反作用。冪等性屬於語義範疇,正如編譯器只能幫助檢查語法錯誤同樣,HTTP規範也沒有辦法經過消息格式等語法手段來定義它,這多是它不太受到重視的緣由之一。但實際上,冪等性是分佈式系統設計中十分重要概念,而HTTP的分佈式本質也決定了它在HTTP中具備重要地位。

     

    分佈式事務 vs 冪等設計

    爲何須要冪等性呢?咱們先從一個例子提及,假設有一個從帳戶取錢的遠程API(能夠是HTTP的,也能夠不是),咱們暫時用類函數的方式記爲: 

    bool withdraw(account_id, amount)

    withdraw的語義是從account_id對應的帳戶中扣除amount數額的錢;若是扣除成功則返回true,帳戶餘額減小amount;若是扣除失敗則返回false,帳戶餘額不變。值得注意的是:和本地環境相比,咱們不能輕易假設分佈式環境的可靠性。一種典型的狀況是withdraw請求已經被服務器端正確處理,但服務器端的返回結果因爲網絡等緣由被掉丟了,致使客戶端沒法得知處理結果。若是是在網頁上,一些不恰當的設計可能會使用戶認爲上一次操做失敗了,而後刷新頁面,這就致使了withdraw被調用兩次,帳戶也被多扣了一次錢。如圖1所示:

    non-idemponent

    圖1

    這個問題的解決方案一是採用分佈式事務,經過引入支持分佈式事務的中間件來保證withdraw功能的事務性。分佈式事務的優勢是對於調用者很簡單,複雜性都交給了中間件來管理。缺點則是一方面架構過重量級,容易被綁在特定的中間件上,不利於異構系統的集成;另外一方面分佈式事務雖然能保證事務的ACID性質,而但卻沒法提供性能和可用性的保證。

    另外一種更輕量級的解決方案是冪等設計。咱們能夠經過一些技巧把withdraw變成冪等的,好比:

    int create_ticket() 

    bool idempotent_withdraw(ticket_id, account_id, amount)

    create_ticket的語義是獲取一個服務器端生成的惟一的處理號ticket_id,它將用於標識後續的操做。idempotent_withdraw和withdraw的區別在於關聯了一個ticket_id,一個ticket_id表示的操做至多隻會被處理一次,每次調用都將返回第一次調用時的處理結果。這樣,idempotent_withdraw就符合冪等性了,客戶端就能夠放心地屢次調用。

    基於冪等性的解決方案中一個完整的取錢流程被分解成了兩個步驟:1.調用create_ticket()獲取ticket_id;2.調用idempotent_withdraw(ticket_id, account_id, amount)。雖然create_ticket不是冪等的,但在這種設計下,它對系統狀態的影響能夠忽略,加上idempotent_withdraw是冪等的,因此任何一步因爲網絡等緣由失敗或超時,客戶端均可以重試,直到得到結果。如圖2所示:

    image

    圖2

    和分佈式事務相比,冪等設計的優點在於它的輕量級,容易適應異構環境,以及性能和可用性方面。在某些性能要求比較高的應用,冪等設計每每是惟一的選擇。

     

    HTTP的冪等性

    HTTP協議自己是一種面向資源的應用層協議,但對HTTP協議的使用實際上存在着兩種不一樣的方式:一種是RESTful的,它把HTTP當成應用層協議,比較忠實地遵照了HTTP協議的各類規定;另外一種是SOA的,它並無徹底把HTTP當成應用層協議,而是把HTTP協議做爲了傳輸層協議,而後在HTTP之上創建了本身的應用層協議。本文所討論的HTTP冪等性主要針對RESTful風格的,不過正如上一節所看到的那樣,冪等性並不屬於特定的協議,它是分佈式系統的一種特性;因此,不管是SOA仍是RESTful的Web API設計都應該考慮冪等性。下面將介紹HTTP GET、DELETE、PUT、POST四種主要方法的語義和冪等性。

    HTTP GET方法用於獲取資源,不該有反作用,因此是冪等的。好比:GET http://www.bank.com/account/123456,不會改變資源的狀態,不論調用一次仍是N次都沒有反作用。請注意,這裏強調的是一次和N次具備相同的反作用,而不是每次GET的結果相同。GET http://www.news.com/latest-news這個HTTP請求可能會每次獲得不一樣的結果,但它自己並無產生任何反作用,於是是知足冪等性的。

    HTTP DELETE方法用於刪除資源,有反作用,但它應該知足冪等性。好比:DELETE http://www.forum.com/article/4231,調用一次和N次對系統產生的反作用是相同的,即刪掉id爲4231的帖子;所以,調用者能夠屢次調用或刷新頁面而沒必要擔憂引發錯誤。

    比較容易混淆的是HTTP POST和PUT。POST和PUT的區別容易被簡單地誤認爲「POST表示建立資源,PUT表示更新資源」;而實際上,兩者都可用於建立資源,更爲本質的差異是在冪等性方面。在HTTP規範中對POST和PUT是這樣定義的:

    The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line. ...... If a resource has been created on the origin server, the response SHOULD be 201 (Created) and contain an entity which describes the status of the request and refers to the new resource, and a Location header.

    The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI.

    POST所對應的URI並不是建立的資源自己,而是資源的接收者。好比:POST http://www.forum.com/articles的語義是在http://www.forum.com/articles下建立一篇帖子,HTTP響應中應包含帖子的建立狀態以及帖子的URI。兩次相同的POST請求會在服務器端建立兩份資源,它們具備不一樣的URI;因此,POST方法不具有冪等性。而PUT所對應的URI是要建立或更新的資源自己。好比:PUT http://www.forum/articles/4231的語義是建立或更新ID爲4231的帖子。對同一URI進行屢次PUT的反作用和一次PUT是相同的;所以,PUT方法具備冪等性。

    在介紹了幾種操做的語義和冪等性以後,咱們來看看如何經過Web API的形式實現前面所提到的取款功能。很簡單,用POST /tickets來實現create_ticket;用PUT /accounts/account_id/ticket_id&amount=xxx來實現idempotent_withdraw。值得注意的是嚴格來說amount參數不該該做爲URI的一部分,真正的URI應該是/accounts/account_id/ticket_id,而amount應該放在請求的body中。這種模式能夠應用於不少場合,好比:論壇網站中防止意外的重複發帖。

     

    總結

    上面簡單介紹了冪等性的概念,用冪等設計取代分佈式事務的方法,以及HTTP主要方法的語義和冪等性特徵。其實,若是要追根溯源,冪等性是數學中的一個概念,表達的是N次變換與1次變換的結果相同,有興趣的讀者能夠從Wikipedia上進一步瞭解。

     

    參考

    RFC 2616, Hypertext Transfer Protocol -- HTTP/1.1, Method Definitions

    The Importance of Idempotence

    stackoverflow -  PUT vs POST in REST

    發佈於 9個月前, 閱讀(9) | 評論(0) | 投票(0) | 收藏(0)  閱讀全文...
  • 292012-11
    摘要:HBTC 2012(Hadoop&BigData Technology Conference 2012)即將召開,爲了讓讀者能夠提早了解一下目前國內各個公司在Hadoop和大數據方面的運用,CSDN於會前對演講嘉賓進行了採訪。本期採訪了阿里巴巴的代志遠,他給咱們提早分享了一下HBase在阿里巴巴海量數據部門的實踐。

    【CSDN報道】代志遠早年就任網易研究院從事MapReduce與DFS系統的自主研發,後加入支付寶數據平臺負責Hadoop與HBase體系的架構設計與二次研發,支付寶流計算與分佈式搜索系統的設計和研發,後成爲支付寶海量計算體系架構師兼支付寶三代架構成員。現就轉戰於阿里巴巴集團-CDO-海量數據部門,負責創新性項目的研究和跟進,目前專一於Google第二代數據庫產品MegaStore的研究和在阿里的落地。

    在即將召開的HBTC大會中,咱們有幸邀請到代志遠做爲咱們的演講嘉賓,請他分享下阿里巴巴在海量數據分佈式數據庫領域的探索。咱們也對他提早作了郵件採訪,讓用戶能夠更快地瞭解阿里巴巴海量數據分佈式數據庫以及在Hadoop應用領域的實踐。

    阿里巴巴海量數據部門: 代志遠

    CSDN: Hadoop目前是大數據處理領域的王者,你認爲中小企業應用Hadoop的瓶頸在哪裏?

    代志遠:首先由於Hadoop自己機制複雜,所依賴的參數配置頗多,而且Hadoop須要像數據庫同樣穩定,知足性能的運行,就須要運維人員如同DBA同樣要懂網絡、磁盤、內核以及其餘一些硬件知識,這對於運維人員的要求是比較高的。其次Hadoop社區蓬勃發展,生態圈不斷擴大,用戶不斷增多,規模極限也不斷突破,這就促使了Hadoop的架構和代碼發展很是快並且變動也比較快,正由於如此,系統在快速發展的時候容易引入不少的Bug和一些缺陷(可能由於稍稍的使用不當或比較小的問題就引發總體性能和穩定性的波動)。更重要的是,Hadoop代碼複雜,並且須要與社區接軌,可以找到對Hadoop源碼熟悉並能優化升級和bugfix的人才是很難的,這對於一個公司的研發來講是個很大的挑戰。最後一點是公司的認知,除了相似Cloudera、MapR之類的軟件公司須要對軟件技術負責,其餘多數公司不管大中小都依賴於公司業務,尤爲中小公司業務壓力大、人員緊張,可以從業務研發人員中抽調或經過其餘方式組建專有的Hadoop運維團隊甚至是研發團隊,從公司規劃與發展上來講是比較困難的事情。

    CSDN: Hadoop的本質是爲全量而生,就是說它重吞吐量,響應時間徹底沒有保障,那麼對於像淘寶、天貓在「雙11」活動搶購的時候,須要實時處理數據(多是毫秒級,秒級的響應),是如何進行實現的?

    代志遠:Hadoop是離線計算平臺,其中包括分佈式文件系統(HDFS)和分佈式計算(MapReduce),這自己是沒法對響應時間作保證的。可是目前在Hadoop之上的生態系統愈來愈完善,其中HBase就是支持海量數據、高併發的在線數據庫,應對這種場景就很是適合。HBase在此次雙十一中與MySQL等在線數據庫共同做爲線上庫使用,承擔了重要的責任,並創下了並在全天高壓力之下無端障的佳績。另外非Hadoop生態圈的流式計算框架Storm、S4也一樣能夠爲實時計算分擔必定的壓力。

    CSDN: 你在雲計算大會時作的一場有關HBase的報告,主要講如何用HBase替代MySQL,HBase對比MySQL的優點在哪裏?

    代志遠:準確來講是HBase替換MySQL的一部分應用,這些應用天然是要符合HBase的應用場景(與MySQL對比),好比數據量大、對線性拓展有需求、對自動化運維(負載均衡)有要求並且應用模式簡單。在支付寶中因其增加速度快,業務量大,形成了不少應用都是數據量龐大並且速度增加快,所以有一些應用迫切須要一個數據庫可以支撐如今的業務而下降對關係型的需求,因此嘗試了HBase的解決方案。

    CSDN: 阿里巴巴在部署Hadoop的過程當中有哪些比較好的經驗能夠跟技術人員分享?

    代志遠:最重要的是要有一個完善團隊,健全的流程。

    • 集羣愈來愈大,要樹立以集羣穩定性和性能爲要領的工做思路。
    • 如今進入Hadoop應用開發領域的人變多,但自己知識因其入行遲早而積累不一樣,沒法對集羣的穩定性負責,經常會寫出跑死集羣的任務(數據庫中SQL使用不善也常會如此)。所以要有一個較好的管理流程約束開發人員作到責任分明,以便促使應用開發不只要對本身的任務負責還要對集羣負責,不斷學習和檢查減小故障的產生。
    • 要有一個好的運維團隊,懂硬件、重流程、負責任。
    • 公司在資源和戰略上應有所傾斜,重視研發人員增強在研發的投入,畢竟分佈式系統的入行門檻相比應用開發的技術門檻要高,固然有好的應用架構師可以取長補短規避大多數問題也是可行的,但單一系統的穩定性仍是須要靠人來保證。

    CSDN: 請您簡要介紹一下本次HBTC2012大會上的議題的內容。

    代志遠:06年Google發表論文Bigtable,社區隨之出現HBase,後Google 08年發表第二代數據庫產品MegaStore至今未有社區同類產品出現,現今Google又出現新一代數據庫理論Spanner和F1。 而最近幾年隨之Bigtable和NoSQL的興起,社區產品HBase逐步走向NoSQL系統的主流產品,優點明顯然而缺點也明顯,大數據平臺下的業務由SQL向NoSQL的遷移比較複雜而應用人員學習成本頗高,而且沒法支持事務和多維索引,使得許多業務沒法享用來自NoSQL系統中線性拓展能力。

    Google內部MegaStore就做爲Bigtable的一個補充而出現,在Bigtable的上層支持了SQL,事務、索引、跨機房災備,併成爲大名鼎鼎的Gmail、Google App Engine、Android Market的底層存儲。所以咱們決定以MegaStore爲理論模型進行探索如何在HBase系統上不犧牲線性拓展能力,同時又能提供跨行事務、索引、SQL的功能。

    HBase系統故障恢復的優化實踐

    其實在第四屆中國雲計算大會上,當時還在支付寶數據平臺的架構師代志遠就爲你們帶來了題爲「HBase系統故障恢復的優化實踐分享」的精彩演講,他分析了支付寶海量數據在線處理的現狀,以HBase解決方案取代傳統MySQL解決方案的技術歷程,並詳盡分享了Region Server的宕機恢復流程(閱讀全文)。

    在Hadoop的體系當中,支持實時的一條線,HBase,支持海量數據庫初衷的時候,設計爲了設計萬一級實時數據庫,HBase這個東西通過這幾年的發展,已經逐漸成爲目前業界當中主要的實時數據庫,分佈式數據庫,像支付寶直接上HBase系統,就是考慮到HBase的先進架構,可以幫助支付寶完成如今不少的海量數據的存儲以及在線隨機讀寫高性能的訪問和存儲。

    不過在HBase的系統當中,體現它的可用性有幾個風險。第一個是HBase自己在底層依賴的HDFS,加載了惟一一塊數據,單臺機器保證一致性,HDFS保持了冗餘。第二點,恢復過程中,Failover過程很是複雜,這個時間消耗越長,做爲在線系統,這種時間越長可能會影響到在線訪問用戶體驗。第三點它依賴的HDFS,HBase做爲在線數據庫依賴HDFS有故障的,通過幾小時恢復提供生產業務,對業務方沒有直接感覺,做爲在線系統若是掛掉,若是須要通過近小時恢復時間,恐怕就會直接收到自於支付寶外部的用戶投訴了。HBase目前它本身的監控體系尚不完善,目前的監控力度很是得粗,只能監控到單臺的Region Server的狀況,看不到當前用戶表有多少讀寫比例,看不到當前服務結點寫做量多少,讀出量多少。

    Region Server在恢復過程中有幾個流程這個流程很複雜,流程很是很是多,以當前的系統規模,它凸顯出來的問題,這幾個流程是影響到它的恢復速度的關鍵流程。等待時間週期很是長,週期之因此比較長,是由於如今的機器發展速度很是得快,每臺機器從兩個G到8個G,96G,140G的大層次的機器,Java語言實現了系統當中大內存管理自己存在問題,除非革新這門語言,不然別無他法。若是說在設計的參數不合理,就可能會致使一個問題,有可能這臺服務器就會中止運行,發生這麼一次狀況就很是可怕,幾十G的內存這個過程須要幾十秒甚至上分鐘,一般狀況下,咱們會設置到3分鐘,這就意味着,爲了不出現這種問題,就會同時引入新的問題,宕機以後恢復等待時間須要三分鐘。第二個關鍵流程當中,當它感知到已經掛掉了,在線數據庫協助WL數據從新作到存儲當中去,以保證明時更新是同步,不然這個數據庫確定要丟出去,重作數據過程中,會有一個過程,Split Hlog,跟當前數據量有關係,Edit Log數據又比較多,你們在業餘時間能夠進行測試,數據不以支付寶的爲準,以當前數據系統大小爲準。

    第三個關鍵流程,重作完數據以後,這部分從新上線,上線以前進行數據進行二次掃描,告訴系統,Region怎麼加入到Region Server當中去,掃描也存在問題,問題可能引起到兩分鐘到6分鐘,這也跟當前系統數據有關。第四部分,這個過程稱之爲再次上線的過程,這個再次上線,上線時間跟當前這臺機器的Region上線有關係。支付寶面對消費記錄查詢,用戶查不出來數據,15分鐘以後才能查到,在面臨在線問題上這是很是可怕的事情。

    針對Region Server這一關鍵流程,作了一些優化。這個優化正是提到關鍵流程第一點,在判斷宕機超市的狀況下,不強依賴於Zookeeper,支付寶又啓動了監控進程Mirror Process,每一臺,Region Server當中都會起到PID存不存在,這種檢查並不是徹底可靠,當檢查PID不存在,就有理由認爲已經掛掉了,要進行可靠檢查,一般DBA在線判斷數據庫是否可用,一般會用PIng連續服務端口,這就彌補了系動中的調用命令不可靠的事情。最後當發現服務端口不可用時,有理由認爲當前進程已經死掉了,死掉了以後,那麼就按照現有邏輯刪除結點,這三分鐘的時間就徹底省略掉了。(整理/@CSDN王鵬,審校/包研)

    11月30日-12月1日,北京新雲南皇冠假日酒店,業內將迎來國內大數據領域最純粹的技術盛會——HBTC 2012(Hadoop&BigData Technology Conference 2012)。Hadoop及雲計算生態系統的力量齊聚北京,歡迎熱愛開源的朋友們加入!報名網址參見HBTC 2012

    發佈於 1年前, 閱讀(112) | 評論(0) | 投票(0) | 收藏(2)  閱讀全文...
  • 292012-11

    在前面三篇文章中,介紹了關於分佈式系統中數據一致性的問題,這一篇主要介紹CAP定理以及本身對CAP定理的瞭解。

    CAP定理是2000年,由 Eric Brewer 提出來的

    Brewer認爲在分佈式的環境下設計和部署系統時,有3個核心的需求,以一種特殊的關係存在。這裏的分佈式系統說的是在物理上分佈的系統,好比咱們常見的web系統。

    這3個核心的需求是:ConsistencyAvailabilityPartition Tolerance,賦予了該理論另一個名字 - CAP

    Consistency:一致性,這個和數據庫ACID的一致性相似,但這裏關注的全部數據節點上的數據一致性和正確性,而數據庫的ACID關注的是在在一個事務內,對數據的一些約束。

    Availability:可用性,關注的在某個結點的數據是否可用,能夠認爲某一個節點的系統是否可用,通訊故障除外。

    Partition Tolerance:分區容忍性,是否能夠對數據進行分區。這是考慮到性能和可伸縮性。

    爲何不能徹底保證這個三點了,我的以爲主要是由於一旦進行分區了,就說明了必須節點之間必須進行通訊,涉及到通訊,就沒法確保在有限的時間內完成指定的行文,若是要求兩個操做之間要完整的進行,由於涉及到通訊,確定存在某一個時刻只完成一部分的業務操做,在通訊完成的這一段時間內,數據就是不一致性的。若是要求保證一致性,那麼就必須在通訊完成這一段時間內保護數據,使得任何訪問這些數據的操做不可用。

    若是想保證一致性和可用性,那麼數據就不可以分區。一個簡單的理解就是全部的數據就必須存放在一個數據庫裏面,不能進行數據庫拆分。這個對於大數據量,高併發的互聯網應用來講,是不可接受的。

     

    咱們能夠拿一個簡單的例子來講明:假設一個購物系統,賣家A和賣家B作了一筆交易100元,交易成功了,買家把錢給賣家。

    這裏面存在兩張表的數據:Trade表Account表 ,涉及到三條數據Trade(100),Account A ,Account B

    假設 trade表和account表在一個數據庫,那麼只須要使用數據庫的事務,就能夠保證一致性,同時不會影響可用性。可是隨着交易量愈來愈大,咱們能夠考慮按照業務分庫,把交易庫和account庫單獨分開,這樣就涉及到trade庫和account庫進行通訊,也就是存在了分區,那麼咱們就不可能同時保證可用性和一致性。

    咱們假設初始狀態

    trade(buyer,seller,tradeNo,status) = trade(A,B,20121001,I)

    account(accountNo,balance) = account(A,300)

    account(accountNo,balance) = account(B,10)

    在理想狀況下,咱們指望的狀態是

    trade(buyer,seller,tradeNo,status) = trade(A,B,20121001,S)

    account(accountNo,balance) = account(A,200)

    account(accountNo,balance) = account(B,110)

     

    可是考慮到一些異常狀況

    假設在trade(20121001,S)更新完成以前,賬戶A進行扣款以後,賬戶A進行了另一筆300款錢的交易,把錢消費了,那麼就存在一個狀態

    trade(buyer,seller,tradeNo,status) = trade(A,B,20121001,S)

    account(accountNo,balance) = account(A,0)

    account(accountNo,balance) = account(B,10)

    產生了數據不一致的狀態

     

    因爲這個涉及到資金上的問題,對資金要求比較高,咱們必須保證一致性,那麼怎麼辦,只能在進行trade(A,B,20121001)交易的時候,對於任何A的後續交易請求trade(A,X,X),必須等到A完成以後,纔可以進行處理,也就是說在進行trade(A,B,20121001)的時候,Account(A)的數據是不可用的。

     

    任何架構師在設計分佈式的系統的時候,都必須在這三者之間進行取捨。首先就是是否選擇分區,因爲在一個數據分區內,根據數據庫的ACID特性,是能夠保證一致性的,不會存在可用性和一致性的問題,惟一須要考慮的就是性能問題。對於可用性和一致性,大多數應用就必須保證可用性,畢竟是互聯網應用,犧牲了可用性,至關於間接的影響了用戶體驗,而惟一能夠考慮就是一致性了。

     

    犧牲一致性

    對於犧牲一致性的狀況最多的就是緩存和數據庫的數據同步問題,咱們把緩存看作一個數據分區節點,數據庫看做另一個節點,這兩個節點之間的數據在任什麼時候刻都沒法保證一致性的。在web2.0這樣的業務,開心網來舉例子,訪問一個用戶的信息的時候,能夠先訪問緩存的數據,可是若是用戶修改了本身的一些信息,首先修改的是數據庫,而後在通知緩存進行更新,這段期間內就會致使的數據不一致,用戶可能訪問的是一個過時的緩存,而不是最新的數據。可是因爲這些業務對一致性的要求比較高,不會帶來太大的影響。

     

    異常錯誤檢測和補償

    還有一種犧牲一致性的方法就是經過一種錯誤補償機制來進行,能夠拿上面購物的例子來講,假設咱們把業務邏輯順序調整一下,先扣買家錢,而後更新交易狀態,在把錢打給賣家

    咱們假設初始狀態

    account(accountNo,balance) = account(A,300)

    account(accountNo,balance) = account(B,10)

    trade(buyer,seller,tradeNo,status) = trade(A,B,20121001,I)

     

    那麼有可能出現

    account(accountNo,balance) = account(A,200)

    trade(buyer,seller,tradeNo,status) = trade(A,B,20121001,S)

    account(accountNo,balance) = account(B,10)

     

    那麼就出現了A扣款成功,交易狀態也成功了,可是錢沒有打給B,這個時候能夠經過一個時候的異常恢復機制,把錢打給B,最終的狀況保證了一致性,在必定時間內數據多是不一致的,可是不會影響太大。

     

    兩階段提交協議

    固然,還有一種方式就是我另一篇文章裏面《X/Open DTP-分佈式事務模型》裏面說的,可是再第一階段和第二階段之間,數據也可不能是一致性的,也可能出現一樣的狀況致使異常。並且DTP的分佈式事務模型 限制太多,例如必須有實現其功能的相關的容器支持,而且資源管理器也必須實現了XA規範。限制比較多。

     

    國外有的架構師有兩種方案去解決CAP的限制,可是也是比較適合特定的業務,而沒有通用的解決方案,

    探知分區->分區內操做->過後補償

    就是上面介紹的異常檢測恢復機制,這種機制其實仍是有限制,

    首先對於分區檢測操做,不一樣的業務涉及到的分區操做可能不同

    分區內操做限制:不一樣的業務對應的約束不一致

    過後補償:因爲業務約束不同,補償方式也不同。

    因此這隻能做爲一種思想,不能作一個通用的解決方案

     

     

    轉載自:http://www.cnblogs.com/aigongsi/archive/2012/10/15/2721366.html

    發佈於 1年前, 閱讀(69) | 評論(0) | 投票(0) | 收藏(0)  閱讀全文...
  • 292012-11
    關於分佈式系統的數據一致性問題(三)

    在個人博文裏面 關於分佈式系統的數據一致性問題(二) 裏面主要介紹了數據分佈的狀況下保證一致性的狀況,在第二篇文章裏面,我這裏提出了三個問題

    1. 訂單系統調用支付系統支付訂單,支付成功,可是返回給訂單系統數據超時,訂單仍是I(初始狀態),可是此時會員賬戶餘額100,會員確定會立刻找京東罵京東,爲啥不給老子發貨,我都付錢了
    2. 訂單系統調用支付系統成功,狀態也已經更新成功,可是通知倉庫發貨失敗,這個時候訂單是P(已支付)狀態,此時會員賬戶餘額是100,可是倉庫不會發貨。會員也要罵京東。
    3. 訂單系統調用支付系統成功,狀態也已經更新成功,而後通知倉庫發貨,倉庫告訴訂單系統,沒有貨了。這個時候數據狀態和第二種狀況同樣。

     

    重點分析解決了第一個的問題以及相應的方案,發如今數據分佈的環境下,很難絕對的保證數據一致性(任何一段區間),可是有辦法經過一種補償機制,最終保證數據的一致性。

     

    在下面在分析一下第二個問題

    • 訂單系統調用支付系統成功,狀態也已經更新成功,可是通知倉庫發貨失敗,這個時候訂單是P(已支付)狀態,此時會員賬戶餘額是100,可是倉庫不會發貨。會員也要罵京東。

    經過在上一篇文章裏面分析過,這個相對來講是比較簡單的,我能夠採起重試機制,若是發現通知倉庫發貨失敗,就一致重試,

    這裏面有兩種方式:

    1 異步方式:經過相似MQ(消息通知)的機制,這個是異步的通知

    2 同步調用:相似於遠程過程調用

    對於同步的調用的方式,比較簡單,咱們可以及時獲取結果,對於異步的通知,就必須採用請求,應答的方式進行,這一點在(關於分佈式系統的數據一致性問題(一))裏面有介紹。這裏面就再也不闡述。

     

    來看看第三個問題

    • 訂單系統調用支付系統成功,狀態也已經更新成功,而後通知倉庫發貨,倉庫告訴訂單系統,沒有貨了。這個時候數據狀態和第二種狀況同樣。

    我以爲這是一個頗有意思的問題,咱們仍是考慮幾種解決的方案

    1 在會員下單的時刻,就告訴倉庫,我要你把貨物留下來,

    2 在會員支付訂單時候,在支付以前檢查倉庫有沒有貨,若是沒有貨,就告知會員木有貨物了

    3 若是會員支付成功,這個時候沒有貨了,就會退款給用戶或者等待有貨的時候在發貨

     

    正常狀況,京東的倉庫通常都是有貨的,因此影響到的會員不多,可是在秒殺和營銷的時候,這個時候就不必定了,咱們考慮假設倉庫有10臺iphone

    若是採用第一種方案,

    1 在會員下單的時候,至關於庫存就-1,那麼用戶惡意拍下來,沒有去支付,就影響到了其餘用戶的購買。京東能夠設置一個訂單超時時間,若是這段時間內沒有支付,就自動取消訂單

    2 在會員支付以前,檢查倉庫有貨,這種方案了,對於用戶體驗很差,可是對於京東比較好,至少我東西都賣出去了。那些沒有及時付款的用戶,只能投訴了京東無端取消訂單

    3 第三種方案,這個方案體驗更很差,並且用戶感受受到京東欺詐,可是對於京東來講,比第二種方案更有益,畢竟我還能夠多賣出一點東西。

     

    我的以爲,京東應該會採用第二種或者第三種方式來處理這類狀況,我在微博上搜索了 「京東 無端取消訂單」,發現果然和我預料的處理方式。不過至於這裏的無端取消是否是技術上的緣由我不知道,若是真的是技術上的緣由,我以爲京東能夠採用不一樣的處理方案。對於秒殺和促銷商品,能夠考慮第一種方案,大多數人都會直接付款,畢竟便宜啊,若是用戶搶不到便宜的東西,抱怨固然很大了。這樣能夠照顧大多數用戶的體驗。對於通常的訂單,能夠採用第二種或者第三種方式,這種狀況下,發生付款以後倉庫沒有貨的狀況會比較少,而且就算髮生了,用戶也會以爲無所謂,大不了退錢嗎,這樣就能夠實現本身的利益最大化而最低程度的減小用戶體驗。

     

    而鐵道部在這個問題上,採用的是第一種方案,爲何和京東不同,就是由於用戶體驗,若是用戶把票都買了,你告訴我木有票了,旅客會殺人的。哈哈,不過鐵道部不擔憂票賣不出去,第一種方案對他影響沒有什麼。

     

    說了這麼多,就是說 分佈式環境下(數據分佈)要任什麼時候刻保證數據一致性是不可能的,只能採起妥協的方案來保證數據最終一致性。這個也就是著名的CAP定理。

     

    轉載自:http://www.cnblogs.com/aigongsi/archive/2012/09/25/2701396.html


    發佈於 1年前, 閱讀(36) | 評論(0) | 投票(0) | 收藏(0)  閱讀全文...
  • 292012-11

    分佈式系統的數據一致性問題(一)裏面,簡單的介紹了分佈式數據的同步問題,上面的問題比較抽象,在目前的互聯網應用中還不多見,此次在經過一個比較常見的例子,讓你們更深刻的瞭解一下分佈式系統設計中關於數據一致性的問題

     

    此次咱們拿咱們常用的功能來考慮吧,最近網購比較熱門,就以京東爲例的,咱們來看看京東的一個簡單的購物流程

     

    用戶在京東上下了一個訂單,發現本身在京東的帳戶裏面有餘額,而後使用餘額支付,支付成功以後,訂單狀態修改成支付成功,而後通知倉庫發貨。假設訂單系統,支付系統,倉庫系統是三個獨立的應用,是獨立部署的,系統之間經過遠程服務調用。

    訂單的有三個狀態:I:初始 P:已支付 W:已出庫,訂單金額100, 會員賬戶餘額200

    若是整個流程比較順利,正常狀況下,訂單的狀態會變爲I->P->W,會員賬戶餘額100,訂單出庫。

     

    可是若是流程不順利了?考慮如下幾種狀況

    1:訂單系統調用支付系統支付訂單,支付成功,可是返回給訂單系統數據超時,訂單仍是I(初始狀態),可是此時會員賬戶餘額100,會員確定會立刻找京東罵京東,爲啥不給老子發貨,我都付錢了

    2:訂單系統調用支付系統成功,狀態也已經更新成功,可是通知倉庫發貨失敗,這個時候訂單是P(已支付)狀態,此時會員賬戶餘額是100,可是倉庫不會發貨。會員也要罵京東。

    3:訂單系統調用支付系統成功,狀態也已經更新成功,而後通知倉庫發貨,倉庫告訴訂單系統,沒有貨了。這個時候數據狀態和第二種狀況同樣。

     

    對於問題一,咱們來分析一下解決方案,能想到的解決方案以下

    1 假設調用支付系統支付訂單的時候先不扣錢,訂單狀態更新完成以後,在通知支付系統你扣錢

    若是採用這種設計方案,那麼在同一時刻,這個用戶,又支付了另一筆訂單,訂單價格200,順利完成了整個訂單支付流程,因爲當前訂單的狀態已經變成了支付成功,可是實際用戶已經沒有錢支付了,這筆訂單的狀態就不一致了。即便用戶在同一個時刻沒有進行另外的訂單支付行爲,通知支付系統扣錢這個動做也有可能完不成,由於也有可能失敗,反而增長了系統的複雜性。

     

    2 訂單系統自動發起重試,多重試幾回,例如三次,直到扣款成功爲止。

    這個看起來也是不錯的考慮,可是和解決方案同樣,解決不了問題,還會帶來新的問題,假設訂單系統第一次調用支付系統成功,可是沒有辦法收到應答,訂單系統又發起調用,完了,重複支付,一次訂單支付了200。

    假設支付系統正在發佈,你重試多少次都同樣,都會失敗。這個時候用戶在等待,你怎麼處理?

     

    3 在第二種方案的基礎上,咱們先解決訂單的重複支付行爲,咱們須要在支付系統上對訂單號進行控制,一筆訂單若是已經支付成功,不能在進行支付。返回重複支付標識。那麼訂單系統根據返回的標識,更新訂單狀態。

    接下來解決重試問題,咱們假設應用上重試三次,若是三次都失敗,先返回給用戶提示支付結果未知。假設這個時候用戶從新發起支付,訂單系統調用支付系統,發現訂單已經支付,那麼繼續下面的流程。若是會員沒有發起支付,系統定時(一分鐘一次)去核對訂單狀態,若是發現已經被支付,則繼續後續的流程。

     

    這種方案,用戶體驗很是差,告訴用戶支付結果未知,用戶必定會罵你,你丫咋回事情,我明明支付了,你告訴我未知。假設告訴用戶支付失敗,萬一實際是成功的咋辦。你告訴用戶支付成功,萬一支付失敗咋辦。

     

    4 第三種方案可以解決訂單和支付數據的一致性問題,可是用戶體驗很是差。固然這種狀況比較多是少數,能夠犧牲這一部分的用戶體驗,咱們還有沒有更好的解決方案,既能照顧用戶體驗,又可以保證資金的安全性。

    咱們再回來看看第一種方案,咱們先不扣錢,可是有木有辦法讓這一部分錢不讓用戶使用,對了,咱們先把這一部分錢凍結起來,訂單系統先調用支付系統成功的時候,支付系統先不扣錢,而是先把錢凍結起來,不讓用戶給其餘訂單支付,而後等訂單系統把訂單狀態更新爲支付成功的時候,再通知支付系統,你扣錢吧,這個時候支付系統扣錢,完成後續的操做。

     

    看起來這個方案不錯,咱們仔細在分析一下流程,這個方案還存在什麼問題,假設訂單系統在調用支付系統凍結的時候,支付系統凍結成功,可是訂單系統超時,這個時候返回給用戶,告知用戶支付失敗,若是用戶再次支付這筆訂單,那麼因爲支付系統進行控制,告訴訂單系統凍結成功,訂單系統更新狀態,而後通知支付系統,扣錢吧。若是這個時候通知失敗,木有問題,反正錢都已是凍結的了,用戶不能用,我只要定時掃描訂單和支付狀態,進行扣錢而已。

     

    那麼若是變態的用戶從新拍下來一筆訂單,100塊錢,對新的訂單進行支付,這個時候因爲先前那一筆訂單的錢被凍結了,這個時候用戶餘額剩餘100,凍結100,發現可用的餘額足夠,那就直接在對用戶扣錢。這個時候餘額剩餘0,凍結100。先前那一筆怎麼辦,一個辦法就是定時掃描,發現訂單狀態是初始的話,就對用戶的支付餘額進行解凍處理。這個時候用戶的餘額變成100,訂單數據和支付數據又一致了。假設原先用戶餘額只有100,被凍結了,用戶從新下單,支付的時候就失敗了啊,的確會發生這一種狀況,因此要儘量的保證在第一次訂單結果不明確的狀況,儘早解凍用戶餘額,好比10秒以內。可是無論如何快速,總有數據不一致的時刻,這個是沒有辦法避免的。

     

    第二種狀況和第三種狀況如何處理,下次在分析吧。

    因爲互聯網目前愈來愈強調分佈式架構,若是是交易類系統,面臨的將會是分佈式事務上的挑戰。固然目前有不少開源的分佈式事務產品,例如java JPA,可是這種解決方案的成本是很是高的,並且實現起來很是複雜,效率也比較低下。對於極端的狀況:例如發佈,故障的時候都是沒有辦法保證強一致性的。

     

    轉載自:http://www.cnblogs.com/aigongsi/archive/2012/09/22/2698055.html

    發佈於 1年前, 閱讀(41) | 評論(0) | 投票(0) | 收藏(1)  閱讀全文...
  • 292012-11
    關於分佈式系統的數據一致性問題(一)

     

    先把問題簡單化處理,假設A增長一條記錄Message_A,發送到M,B增長一條記錄 MESSAGE_B發送到M,都是經過MQ服務器進行轉發,那麼M系統接收到條消息,增長兩條數據,那麼M在把增長的消息羣發給A,B,A和B找到本身缺失的數據,更新數據庫。這樣就完成了一個數據的同步。

     

    從正常狀況下來看,都沒有問題,邏輯徹底合理,可是請考慮如下三個問題

    1 如何保證A->M的消息,M必定接收到了,一樣,如何保證M->A的消息,M必定接收到了

    2 若是數據須要一致性更新,好比A發送了三條消息給M,M要麼所有保存,要麼所有不保存,不可以只保存其中的幾條記錄。咱們假設更新的數據是一條條發送的。

    3 假設同時A發送了多條更新請求,如何保證順序性要求?

     

    這兩個問題就是分佈式環境下數據一致性的問題

    對於第一個問題,比較好解決,咱們先看看一個tcp/ip協議連接創建的過程

    咱們的思路能夠從這個上面出發,在簡化一下,就一個請求,一個應答。

    簡單的通訊模型是這樣的

    A->M : 你收到個人一條消息沒有,消息的ID是12345

    M->A:  我收到了你的一條消息數據,消息數據是ID;12345

    這樣就一個請求,一個應答,就完成了一次可靠性的傳輸。若是A一致沒有收到M的應答,就不斷的重試。這個時候M就必須保證冪等性。不能重複的處理消息。那麼最極端的狀況是,怎麼也收不到M的應答,這個時候是系統故障。本身檢查一下吧。

    這麼設計就要求,A在發送消息的時候持久化這個消息的數據內容,而後不斷的重試,一旦接收到M的應答,就刪除這條消息。一樣,M端也是同樣的。不要相信MQ的持久化機制,不是很靠譜的。

    那麼M給A發送消息也採起相似的原理就能夠了。

     

    下面在看看第二個問題,如何保持數據的一致性更新,這個仍是能夠參考TCP/IP的協議。

    首先A發送一條消息給M:我要發送一批消息數據給你,批次號是10000,數據是5條。

    M發送一條消息給A:ok,我準備好了,批次號是10000,發送方你A

    接着A發送5條消息給M,消息ID分別爲1,2,3,4,5 ,批次號是10000,

    緊接着,A發送一個信息給M:我已經完成5小消息的發送,你要提交數據更新了

     

    接下來可能發送兩種狀況

    1 那麼M發送消息給A:ok,我收到了5條消息,開始提交數據

    2 那麼M也能夠發送給A:我收到了5條消息,可是還缺乏,請你從新發送,那麼A就繼續發送,直到A收到M成功的應答。

    整個過程至關複雜。這個也就是數據一旦分佈了,帶來最大的問題就是數據一致性的問題。這個成本很是高。

     

    對於第三個問題,這個就比較複雜了

    這個最核心的問題就是消息的順序性,咱們只能在每一個消息發一個消息的序列號,可是仍是沒有最好解決這個問題的辦法。由於消息接收方不知道順序。由於即便給他了序列號,也沒有辦法告訴他,這個應該什麼時候處理。最好的辦法是在第二種方式的基礎做爲一個批次來更新。

     

    這個只是以最簡單的例子來講明一下分佈式系統的要保證數據一致性是一件代價很大的事情。固然有的博主會說,這個何須這麼複雜,直接數據庫同步不就能夠了。這個例子固然是沒有問題的,萬一這個幾個庫的模型都不同,我發送消息要處理的事情不同的。怎麼辦?

     

    轉載自:http://www.cnblogs.com/aigongsi/archive/2012/09/21/2696773.html

  • 相關文章
    相關標籤/搜索