海量數據的分庫分表技術演進,最佳實踐

每一個優秀的程序員和架構師都應該掌握分庫分表,移動互聯網時代,海量的用戶天天產生海量的數量html

用戶表程序員

訂單表sql

交易流水錶數據庫

以支付寶用戶爲例,8億;微信用戶更是10億。訂單表更誇張,好比美團外賣,天天都是幾千萬的訂單。淘寶的歷史訂單總量應該百億,甚至千億級別,這些海量數據遠不是一張表能Hold住的。事實上MySQL單表能夠存儲10億級數據,只是這時候性能比較差,業界公認MySQL單表容量在1KW如下是最佳狀態,由於這時它的BTREE索引樹高在3~5之間。緩存

既然一張表沒法搞定,那麼就想辦法將數據放到多個地方,目前比較廣泛的方案有3個:微信

分區;網絡

分庫分表;架構

NoSQL/NewSQL;併發

說明:只分庫,或者只分表,或者分庫分表融合方案都統一認爲是分庫分表方案,由於分庫,或者分表只是一種特殊的分庫分表而已。NoSQL比較具備表明性的是MongoDB,es。NewSQL比較具備表明性的是TiDB。elasticsearch

Why Not NoSQL/NewSQL?

首先,爲何不選擇第三種方案NoSQL/NewSQL,我認爲主要是RDBMS有如下幾個優勢:

   - RDBMS生態完善;

   - RDBMS絕對穩定;

   - RDBMS的事務特性;

NoSQL/NewSQL做爲新生兒,在咱們把可靠性當作首要考察對象時,它是沒法與RDBMS相提並論的。RDBMS發展幾十年,只要有軟件的地方,它都是核心存儲的首選。

目前絕大部分公司的核心數據都是:以RDBMS存儲爲主,NoSQL/NewSQL存儲爲輔!互聯網公司又以MySQL爲主,國企&銀行等不差錢的企業以Oracle/DB2爲主!NoSQL/NewSQL宣傳的不管多牛逼,就如今各大公司對它的定位,都是RDBMS的補充,而不是取而代之!

Why Not 分區?

咱們再看分區表方案。瞭解這個方案以前,先了解它的原理:

 

事實上,這個方案也不錯,它對用戶屏蔽了sharding的細節,即便查詢條件沒有sharding column,它也能正常工做(只是這時候性能通常)。不過它的缺點很明顯:不少的資源都受到單機的限制,例如鏈接數,網絡吞吐等!雖然每一個分區能夠獨立存儲,可是分區表的總入口仍是一個MySQL示例。從而致使它的併發能力很是通常,遠遠達不到互聯網高併發的要求!

至於網上提到的一些其餘缺點好比:沒法使用外鍵,不支持全文索引。我認爲這都不算缺點,21世紀的項目若是仍是使用外鍵和數據庫的全文索引,我都懶得吐槽了!

因此,若是使用分區表,你的業務應該具有以下兩個特色:

數據不是海量(分區數有限,存儲能力就有限);

併發能力要求不高;

Why 分庫分表?

最後要介紹的就是目前互聯網行業處理海量數據的通用方法:分庫分表

雖然你們都是採用分庫分表方案來處理海量核心數據,可是尚未一個一統江湖的中間件,筆者這裏列舉一些有必定知名度的分庫分表中間件:

阿里的TDDL,DRDS和cobar,

開源社區的sharding-jdbc(3.x已經改名爲sharding-sphere);

民間組織的MyCAT;

360的Atlas;

美團的zebra;

 

其餘好比網易,58,京東等公司都有自研的中間件。總之各自爲戰,也能夠說是百花齊放。

可是這麼多的分庫分表中間件所有能夠歸結爲兩大類型:

CLIENT模式

PROXY模式

CLIENT模式表明有阿里的TDDL,開源社區的sharding-jdbc(sharding-jdbc的3.x版本即sharding-sphere已經支持了proxy模式)。架構以下:

 

PROXY模式表明有阿里的cobar,民間組織的MyCAT。架構以下:

 

可是,不管是CLIENT模式,仍是PROXY模式。幾個核心的步驟是同樣的:SQL解析,重寫,路由,執行,結果歸併

 

接下來,以幾個常見的大表爲案例,說明分庫分表如何落地!

實戰案例

分庫分表第一步也是最重要的一步,即sharding column的選取,sharding column選擇的好壞將直接決定整個分庫分表方案最終是否成功。而sharding column的選取跟業務強相關,筆者認爲選擇sharding column的方法最主要分析你的API流量,優先考慮流量大的API,將流量比較大的API對應的SQL提取出來,將這些SQL共同的條件做爲sharding column。例如通常的OLTP系統都是對用戶提供服務,這些API對應的SQL都有條件用戶ID,那麼,用戶ID就是很是好的sharding column。

這裏列舉分庫分表的幾種主要處理思路:

只選取一個sharding column進行分庫分表 ; 

多個sharding column多個分庫分表;

sharding column分庫分表 + es;

再以幾張實際表爲例,說明如何分庫分表。

訂單表

訂單表幾個核心字段通常以下:

 

 

以阿里訂單系統爲例(參考《企業IT架構轉型之道:阿里巴巴中臺戰略思想與架構實現》),它選擇了三個column做爲三個獨立的sharding column,即:orderid,userid,merchantcode。userid和merchantcode就是買家ID和賣家ID,由於阿里的訂單系統中買家和賣家的查詢流量都比較大,而且查詢對實時性要求都很高。而根據orderid進行分庫分表,應該是根據order_id的查詢也比較多。

這裏還有一點須要說起,多個sharding-column的分庫分表是冗餘全量仍是隻冗餘關係索引表,須要咱們本身權衡。

冗餘全量的狀況以下--每一個sharding列對應的表的數據都是全量的,這樣作的優勢是不須要二次查詢,性能更好,缺點是比較浪費存儲空間(淺綠色字段就是sharding-column):

 

冗餘關係索引表的狀況以下--只有一個sharding column的分庫分表的數據是全量的,其餘分庫分表只是與這個sharding column的關係表,這樣作的優勢是節省空間,缺點是除了第一個sharding column的查詢,其餘sharding column的查詢都須要二次查詢,這三張表的關係以下圖所示(淺綠色字段就是sharding column):

 

冗餘全量表PK.冗餘關係表

1.速度對比:冗餘全量表速度更快,冗餘關係表須要二次查詢,即便有引入緩存,仍是多一次網絡開銷;

2.存儲成本:冗餘全量表須要幾倍於冗餘關係表的存儲成本;

3.維護代價:冗餘全量表維護代價更大,涉及到數據變動時,多張表都要進行修改。

 

用戶表

用戶表幾個核心字段通常以下:

通常用戶登陸場景既能夠經過mobileno,又能夠經過email,還能夠經過username進行登陸。可是一些用戶相關的API,又都包含userid,那麼可能須要根據這4個column都進行分庫分表,即4個列都是sharding-column。

帳戶表

帳戶表幾個核心字段通常以下:

 

與帳戶表相關的API,通常條件都有accountno,因此以accountno做爲sharding-column便可。

複雜查詢

上面提到的都是條件中有sharding column的SQL執行。可是,總有一些查詢條件是不包含sharding column的,同時,咱們也不可能爲了這些請求量並不高的查詢,無限制的冗餘分庫分表。那麼這些條件中沒有sharding column的SQL怎麼處理?以sharding-jdbc爲例,有多少個分庫分表,就要併發路由到多少個分庫分表中執行,而後對結果進行合併。具體如何合併,能夠看筆者sharding-jdbc系列文章,有分析源碼講解合併原理。

這種條件查詢相對於有sharding column的條件查詢性能很明顯會降低不少。若是有幾十個,甚至上百個分庫分表,只要某個表的執行因爲某些因素變慢,就會致使整個SQL的執行響應變慢,這很是符合木桶理論。

更有甚者,那些運營系統中的模糊條件查詢,或者上十個條件篩選。這種狀況下,即便單表都很差建立索引,更不要說分庫分表的狀況下。那麼怎麼辦呢?這個時候大名鼎鼎的elasticsearch,即es就派上用場了。將分庫分表全部數據全量冗餘到es中,將那些複雜的查詢交給es處理。

淘寶個人全部訂單頁面以下,篩選條件有多個,且商品標題能夠模糊匹配,這即便是單表都解決不了的問題(索引知足不了這種場景),更不要說分庫分表了:

 

因此,以訂單表爲例,整個架構以下:

 

具體狀況具體分析:多sharding column不到萬不得已的狀況下最好不要使用,成本較大,上面提到的用戶表筆者就不太建議使用。由於用戶表有一個很大的特色就是它的上限是確定的,即便全球70億人全是你的用戶,這點數據量也不大,因此筆者更建議採用單sharding column + es的模式簡化架構。

es+HBase簡要

這裏須要提早說明的是,solr+HBase結合的方案在社區中出現的頻率可能更高,本篇文章爲了保持一致性,全部全文索引方案選型都是es。至於es+HBase和solr+HBase孰優孰劣,或者說es和solr孰優孰劣,不是本文須要討論的範疇,事實上也沒有太多討論的意義。es和solr本就是兩個很是優秀且旗鼓至關的中間件。最近幾年es更火爆:

 

若是拋開選型過程當中全部歷史包袱,單論es+HBase和solr+HBase的優劣,很明顯後者是更好的選擇。solr+HBase高度集成,引入索引服務後咱們最關心,也是最重要的索引一致性問題,solr+HBase已經有了很是成熟的解決方案一一Lily HBase Indexer

延伸閱讀

阿里雲上的雲數據庫HBase版也是藉助solr實現全文索引,有興趣的同窗能夠戳連接瞭解更多:https://help.aliyun.com/product/49055.html?spm=5176.124785.631202.con1.603452c0cz7bj2。

es+HBase原理

剛剛討論到上面的以MySQL爲核心,分庫分表+es的方案,隨着數據量愈來愈來,雖然分庫分表能夠繼續成倍擴容,可是這時候壓力又落到了es這裏,這個架構也會慢慢暴露出問題!

通常訂單表,積分明細表等須要分庫分表的核心表都會有好幾十列,甚至上百列(假設有50列),可是整個表真正須要參與條件索引的可能就不到10個條件(假設有10列)。這時候把50個列全部字段的數據全量索引到es中,對es集羣有很大的壓力,後面的es分片故障恢復也會須要很長的時間。

這個時候咱們能夠考慮減小es的壓力,讓es集羣有限的資源儘量保存條件檢索時最須要的最有價值的數據,即只把可能參與條件檢索的字段索引到es中,這樣整個es集羣壓力減小到原來的1/5(核心表50個字段,只有10個字段參與條件),而50個字段的全量數據保存到HBase中,這就是經典的es+HBase組合方案,即索引與數據存儲隔離的方案

Hadoop體系下的HBase存儲能力咱們都知道是海量的,並且根據它的rowkey查詢性能那叫一個快如閃電。而es的多條件檢索能力很是強大。這個方案把es和HBase的優勢發揮的淋漓盡致,同時又規避了它們的缺點,能夠說是一個揚長避免的最佳實踐。

它們之間的交互大概是這樣的:先根據用戶輸入的條件去es查詢獲取符合過濾條件的rowkey值,而後用rowkey值去HBase查詢,後面這一查詢步驟的時間幾乎能夠忽略,由於這是HBase最擅長的場景,交互圖以下所示:

HBase檢索能力擴展

 

總結

最後,對幾種方案總結以下(sharding column簡稱爲sc):

 

總之,對於海量數據,且有必定的併發量的分庫分表,毫不是引入某一個分庫分表中間件就能解決問題,而是一項系統的工程。須要分析整個表相關的業務,讓合適的中間件作它最擅長的事情。例若有sharding column的查詢走分庫分表,一些模糊查詢,或者多個不固定條件篩選則走es,海量存儲則交給HBase。

作了這麼多事情後,後面還會有不少的工做要作,好比數據同步的一致性問題,還有運行一段時間後,某些表的數據量慢慢達到單表瓶頸,這時候還須要作冷數據遷移。總之,分庫分表是一項很是複雜的系統工程。任何海量數據的處理,都不是簡單的事情,作好戰鬥的準備!

歡迎工做一到五年的Java工程師朋友們加入Java架構開發:860113481

羣內提供免費的Java架構學習資料(裏面有高可用、高併發、高性能及分佈式、Jvm性能調優、Spring源碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)合理利用本身每一分每一秒的時間來學習提高本身,不要再用"沒有時間「來掩飾本身思想上的懶惰!趁年輕,使勁拼,給將來的本身一個交代!

相關文章
相關標籤/搜索