Mysql海量數據存儲和解決方案之一—分佈式DB方案

1)  分佈式DB水平切分中用到的主要關鍵技術:分庫,分表,M-S,集羣,負載均衡數據庫

2) 需求分析:一個大型互聯網應用天天幾十億的PVDB形成了至關高的負載,對系統的穩定性的擴展性帶來極大挑戰。服務器

3) 現有解決方式:經過數據切分提升網站性能,橫向擴展數據層併發

      水平切分DB,有效下降了單臺機器的負載,也減少了宕機的可能性。負載均衡

      集羣方案:解決DB宕機帶來的單點DB不能訪問問題。分佈式

      讀寫分離策略:極大限度提升了應用中Read數據的速度和併發量。性能

      典型例子:Taobao,Alibaba,Tencent,它們大都實現了本身的分佈式數據訪問層(DDAL)。Taobao的基於ibatisSpring的的分佈式數據訪問層,已有多年的應用,運行效率和生產實效性獲得了開發人員和用戶的確定。網站

      水平切分須要考慮的後續問題:分庫後路由規則的選擇和制定,以及後期擴展。如,如何以最少的數據遷移達到最大容量的擴展。因些路由表分規則以及負載均衡的考慮很重要。spa

 

4)對於DB切分,實質上就是數據切分。下面從What, Why, How三個方面來說述。設計

What?什麼是數據切分?日誌

      

      具體將有什麼樣的切分方式呢和路由方式呢?舉個簡單的例子:咱們針對一個Blog應用中的日誌來講明,好比日誌文章(article)表有以下字段:

article_id(int),title(varchar(128)),content(varchar(1024)),user_id(int)

    面對這樣的一個表,咱們怎樣切分呢?怎樣將這樣的數據分佈到不一樣的數據庫中的表中去呢?其實分析blog的應用,咱們不可貴出這樣的結論:blog的應用中,用戶分爲兩種:瀏覽者和blog的主人。瀏覽者瀏覽某個blog,其實是在一個特定的用戶的blog下進行瀏覽的,而blog的主人管理本身的blog,也一樣是在特定的用戶blog下進行操做的(在本身的空間下)。所謂的特定的用戶,用數據庫的字段表示就是「user_id」。就是這個「user_id」,它就是咱們須要的分庫的依據和規則的基礎。咱們能夠這樣作,將user_id110000的全部的文章信息放入DB1中的article表中,將user_id1000120000的全部文章信息放入DB2中的article表中,以此類推,一直到DBn這樣一來,文章數據就很天然的被分到了各個數據庫中,達到了數據切分的目的。接下來要解決的問題就是怎樣找到具體的數據庫呢?其實問題也是簡單明顯的,既然分庫的時候咱們用到了區分字段user_id,那麼很天然,數據庫路由的過程固然仍是少不了user_id的。考慮一下咱們剛纔呈現的blog應用,不論是訪問別人的blog仍是管理本身的blog,總之我都要知道這個blog的用戶是誰吧,也就是咱們知道了這個bloguser_id,就利用這個user_id,利用分庫時候的規則,反過來定位具體的數據庫,好比user_id234,利用該才的規則,就應該定位到DB1,假如user_id12343,利用該才的規則,就應該定位到DB2。以此類推,利用分庫的規則,反向的路由到具體的DB,這個過程咱們稱之爲「DB路由」。

    固然考慮到數據切分的DB設計必然是很是規,不正統的DB設計。那麼什麼樣的DB設計是正統的DB設計呢?

    咱們日常規規矩矩用的基本都是。日常咱們會自覺的按照範式來設計咱們的數據庫,負載高點可能考慮使用相關的Replication機制來提升讀寫的吞吐和性能,這可能已經能夠知足不少需求,但這套機制自身的缺陷仍是比較顯而易見的。上面提到的「自覺的按照範式設計」。考慮到數據切分的DB設計,將違背這個一般的規矩和約束,爲了切分,咱們不得不在數據庫的表中出現冗餘字段,用做區分字段或者叫作分庫的標記字段,好比上面的article的例子中的user_id這樣的字段(固然,剛纔的例子並無很好的體現出user_id的冗餘性,由於user_id這個字段即便就是不分庫,也是要出現的,算是咱們撿了便宜吧)。固然冗餘字段的出現並不僅是在分庫的場景下才出現的,在不少大型應用中,冗餘也是必須的,這個涉及到高效DB的設計。

      

Why?爲何要切分數據?

1)      Oracle這樣成熟穩定的DB能夠支撐海量數據的存儲和查詢,可是價格不是全部人都承受得起。

2)      負載高點時,Master-Slaver模式中存在瓶頸。現有技術中,在負載高點時使用相關的Replication機制來實現相關的讀寫的吞吐性能。這種機制存在兩個瓶頸:一是有效性依賴於讀操做的比例,這裏Master每每會成爲瓶頸所在,寫操做時須要一個順序隊列來執行,過載時Master會承受不住,Slaver的數據同步延遲也會很大,同時還會消耗CPU的計算能力,爲write操做在Master上執行之後仍是須要在每臺slave機器上都跑一次。而Sharding能夠輕鬆的將計算,存儲,I/O並行分發到多臺機器上,這樣能夠充分利用多臺機器各類處理能力,同時能夠避免單點失敗,提供系統的可用性,進行很好的錯誤隔離。

3)      用免費的MySQL和廉價的Server甚至是PC作集羣,達到小型機+大型商業DB的效果,減小大量的資金投入,下降運營成本,何樂而不爲呢?

 

How?如何切分數據?

    先對數據切分的方法和形式進行比較詳細的闡述和說明。

    數據切分能夠是物理上的,對數據經過一系列的切分規則將數據分佈到不一樣的DB服務器上,經過路由規則路由訪問特定的數據庫,這樣一來每次訪問面對的就不是單臺服務器了,而是N臺服務器,這樣就能夠下降單臺機器的負載壓力。

    數據切分也能夠是數據庫內的,對數據經過一系列的切分規則,將數據分佈到一個數據庫的不一樣表中,好比將article分爲article_001,article_002等子表,若干個子表水平拼合有組成了邏輯上一個完整的article表,這樣作的目的其實也是很簡單的。舉個例子說明,好比article表中如今有5000w條數據,此時咱們須要在這個表中增長(insert)一條新的數據,insert完畢後,數據庫會針對這張表從新創建索引,5000w行數據創建索引的系統開銷仍是不容忽視的。可是反過來,假如咱們將這個表分紅100table呢,從article_001一直到article_1005000w行數據平均下來,每一個子表裏邊就只有50萬行數據,這時候咱們向一張只有50w行數據的tableinsert數據後創建索引的時間就會呈數量級的降低,極大了提升了DB的運行時效率,提升了DB的併發量。固然分表的好處還不知這些,還有諸如寫操做的鎖操做等,都會帶來不少顯然的好處。

    綜上,分庫下降了單點機器的負載;分表,提升了數據操做的效率,尤爲是Write操做的效率。

    上文中提到,要想作到數據的水平切分,在每個表中都要有相冗餘字符做爲切分依據和標記字段,一般的應用中咱們選用user_id做爲區分字段,基於此就有以下三種分庫的方式和規則:(固然還能夠有其餘的方式)

按號段分:

(1)    user_id爲區分,11000的對應DB110012000的對應DB2,以此類推;

優勢:可部分遷移

缺點:數據分佈不均

(2)    hash取模分:

user_id進行hash(或者若是user_id是數值型的話直接使用user_id的值也可),而後用一個特定的數字,好比應用中須要將一個數據庫切分紅4個數據庫的話,咱們就用4這個數字對user_idhash值進行取模運算,也就是user_id%4,這樣的話每次運算就有四種可能:結果爲1的時候對應DB1;結果爲2的時候對應DB2;結果爲3的時候對應DB3;結果爲0的時候對應DB4,這樣一來就很是均勻的將數據分配到4DB中。

優勢:數據分佈均勻

缺點:數據遷移的時候麻煩,不能按照機器性能分攤數據

(3)    在認證庫中保存數據庫配置

就是創建一個DB,這個DB單獨保存user_idDB的映射關係,每次訪問數據庫的時候都要先查詢一次這個數據庫,以獲得具體的DB信息,而後才能進行咱們須要的查詢操做。

優勢:靈活性強,一對一關係

缺點:每次查詢以前都要多一次查詢,性能大打折扣

以上就是一般的開發中咱們選擇的三種方式,有些複雜的項目中可能會混合使用這三種

方式。

 

4)      接下來對分佈式數據庫解決海量數據的存訪問題作進一步介紹

分佈式數據方案提供功能以下:

1)提供分庫規則和路由規則(RouteRule簡稱RR),將上面的說明中提到的三中切分規則直接內嵌入本系統,具體的嵌入方式在接下來的內容中進行詳細的說明和論述;

2)引入集羣(Group)的概念,解決容錯性的問題,保證數據的高可用性;

3)引入負載均衡策略(LoadBalancePolicy簡稱LB);

4)引入集羣節點可用性探測機制,對單點機器的可用性進行定時的偵測,以保證LB策略的正確實施,以確保系統的高度穩定性;

5)引入讀/寫分離,提升數據的查詢速度;

相關文章
相關標籤/搜索