<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          也許可能是史上最詳盡的分庫分表文章之一

          共 6073字,需瀏覽 13分鐘

           ·

          2021-05-15 23:33


          趣味性不強,但知識性很強,建議耐心看或者先收藏

          本文內容預覽:

          1. 庫表會在哪天到達瓶頸?
            1.1 蘇寧拼購百萬級庫表拆分之前
            1.2 京東配運平臺庫表拆分之前
            1.3 大眾點評訂單庫拆分之前
            1.4 小結:啥情況需要考慮庫表拆分
          2. 拆分庫表的目的和方案
            2.1 業(yè)務數(shù)據(jù)解耦--垂直拆分
            2.2 解決容量和性能壓力--水平拆分
            2.3 分多少合適
            2.4 怎么分合適
          3. 拆分帶來新的問題
            分區(qū)鍵/唯一ID/數(shù)據(jù)遷移/分布式事務等
          4. 大廠案例,知識回顧擴展
            4.1 螞蟻金服的庫表路由規(guī)則
            4.2 大眾點評分庫分表的數(shù)據(jù)遷移
            4.3 淘寶萬億級交易訂單的存儲引擎

          Part1庫表會在哪天到達瓶頸?

          1.1蘇寧拼購百萬級庫表拆分之前[1]

          蘇寧拼購,蘇寧易購旗下的電商App,18年7月累計用戶突破3000萬。

          圖片來源于QCon大會PPT

          面對千萬級日活 + 千萬級日新增SKU + 千萬級日均訂單,拼購的單庫每天增長數(shù)據(jù)超1億,峰值10萬QPS并發(fā),每個月要搞一次數(shù)據(jù)遷移。

          龐大的數(shù)據(jù)量,對數(shù)據(jù)庫壓力和數(shù)據(jù)運維成本造成了很大的困擾,并且,一旦有一條未命中緩存的SQL,對于整個應用都是災難級的。

          所以,不得不考慮系統(tǒng)的穩(wěn)定性和長遠的業(yè)務支撐。

          1.2京東配運平臺庫表拆分之前[2]

          圖片來源于QCon大會PPT

          起初,用SQL Server存儲,?支撐每天10萬級別業(yè)務量。

          扛不住后,采購了企業(yè)級Oracle/IBM AIX?型機,用 RAC + DataGuard方式,支撐配送所有業(yè)務,到百萬級別單量。但是這種傳統(tǒng)的企業(yè)架構,對于復雜多變的業(yè)務、昂貴的硬件成本、服務的部署和維護成本等痛點,變得越來越突出。

          15年開始,京東配運平臺開始按業(yè)務對數(shù)據(jù)庫做垂直拆分,將存儲容器化,實現(xiàn)了方便的水平擴容、更精細的成本控制、更復雜的業(yè)務形態(tài)支持.

          1.3大眾點評訂單庫拆分之前[3]

          16年前,點評的訂單庫已經超200G容量,面對的越來越復雜的查詢維度,為實現(xiàn)平穩(wěn)查詢,優(yōu)化了索引并增加兩個從庫來分散數(shù)據(jù)庫壓力,但仍有很多效率不理想的數(shù)據(jù)庫請求出現(xiàn)。

          而隨后而來的價格戰(zhàn)、大量搶購的活動開展,訂單數(shù)據(jù)庫很快難以支撐,只能用限流、消息隊列削峰填谷對其進行保護,才能勉強維持日常數(shù)據(jù)讀寫需求。

          而隨著業(yè)務模式的增加,原訂單模型已經不能滿足,如果經常用DDL去建表,建索引對于如此龐大的庫表是非常吃力的,發(fā)生鎖庫鎖表會直接影響線上服務。

          所以,點評團隊以未來十年不再擔心訂單容量為目的,開始進行庫表切分。

          1.4小結:啥情況需要考慮庫表拆分

          實際上,是沒有一個非常量化的指標來判定庫表瓶頸的,因為每個系統(tǒng)的業(yè)務場景,查詢復雜度都有不同。

          但力有窮盡時,我們雖然可以盡量的從加從庫讀寫分離、優(yōu)化sql、優(yōu)化索引、復用連接等等方面進行優(yōu)化,但總會有到達極限的時候的時候,量變引發(fā)質變。甚至,在真實生產環(huán)境,要更加未雨綢繆,不能等到崩了才去考慮。那么,應該怎么去判斷已經到了庫表拆分的時機呢:

          • 硬件性能瓶頸,如果是讀操作多,其實可以加多個從庫分擔主庫讀壓力;但如果是寫操作多,會因為主庫磁盤IO增大,拖慢處理速度;另外,如果單表數(shù)據(jù)量過大,導致索引層級增多,掃描行增多,CPU效率降低,影響sql執(zhí)行效率,拖慢處理速度。而處理速度慢最終會導致連接數(shù)增加直至無連接可用。
          • 日常運維投入,就如蘇寧拼購的情況,如果一個月就要搞一次數(shù)據(jù)遷移,這個人力的投入產出比,應該是完全不匹配的,那就不如一次性搞定它。
          • 業(yè)務發(fā)展可支持程度、難度和風險,當數(shù)據(jù)增長到一定程度,雖然沒有達到極限,還能湊活,但是遇到活動型流量脈沖,無法完全支持業(yè)務需求;而業(yè)務需要進行迭代增加模式時,修改數(shù)據(jù)表帶來的風險又比較大。就可以考慮重構數(shù)據(jù)模型,拆分庫表了。

          Part2拆分庫表的目的和方案

          2.1業(yè)務數(shù)據(jù)解耦--垂直拆分

          把不同的業(yè)務數(shù)據(jù)拆分到各自的數(shù)據(jù)庫中獨立維護,那么最底層的原因是什么呢?

          是微服務下的上層服務拆分。為了滿足快速迭代、安全發(fā)布、鏈路降級、主次業(yè)務解耦等問題,去解決代碼大量沖突、小功能排隊等待大版本發(fā)布等等問題,將業(yè)務按照一定邏輯進行拆解,形成一個個功能完備,獨立運行的服務。[4]

          然而,如果數(shù)據(jù)庫層面不配合,就無法解決根本問題。當上層服務實例拆分后可以被大量橫向擴展,以應對高并發(fā)的流量沖擊,會導致底層數(shù)據(jù)庫的承載壓力和連接數(shù)急劇增加。

          所以,通過垂直拆分將業(yè)務數(shù)據(jù)解耦,各管一事,以滿足微服務的效能最大化。

          2.2解決容量和性能壓力--水平拆分

          對某一業(yè)務庫,當數(shù)據(jù)增量達到了庫瓶頸,或者表瓶頸,就要進行庫表的水平拆分了。

          我之前遇到的很多情況,總是先分表,解決單表的容量和讀寫性能問題,隨著業(yè)務發(fā)展,單庫也遇到瓶頸了再考慮分庫。

          為啥不一步到位?

          就像之前在阿里,新應用上來搞個百庫百表?一來是因為一些用戶規(guī)模和一些路由規(guī)則的問題;更重要的,不是所有公司其實不是所有的公司都和阿里一樣有錢,有限的資源要用在更重要的生存問題上。

          如果你作為一個初創(chuàng)公司的架構,給出了一套可能撐10年的存儲方案,感覺會被同事在心里懟,公司能活3年么就這么浪費?

          但肯定沒有人說這話,因為我們還是希望所有公司都能蓬勃發(fā)展,蒸蒸日上的?。

          所以,拆分方法就很有講究了,怎么分能讓后續(xù)迭代發(fā)展的代價最小呢?

          2.3分多少合適

          表主要看容量,很多經驗表明 上千萬后性能會有顯著下降,因此,我們可以把表容量定在一半多一點,600w。

          庫主要看的是連接數(shù),我們以阿里對外售賣的云存儲來大致估計,單庫的連接數(shù)定在4000左右。

          抽象一個實際的評估案例來看:假如目前平臺每天產生10w訂單,峰值并發(fā)數(shù)8000QPS,然后考慮業(yè)務擴展和增長的速率:

          比如,業(yè)務是和銀行合作擴展業(yè)務,將大小銀行量級平均一下,估計每合作一家可以帶來多大的增長量,這里假設是5000單/天/家,如果業(yè)務計劃是每年度合作10家,那就是5w,5年以后每天的單量,理論上可能會到25w/天。加上現(xiàn)有的10w, 峰值35w。

          如果我們計劃系統(tǒng)的容量需要支撐3年,或者說,3年之后的該業(yè)務擴展會趨于平緩,那么我們可以大致的估計為:

          表:(3年 * 365天 * 35w=3.8億 )/600w = 63 約 64張表.
          庫:10000并發(fā) / 4000 = 2.5 ,可按4個庫來處理

          當然,如果是BAT這種,不缺用戶,不缺錢,又有一些既定路由規(guī)則的情況,還是可以一步到位的。比如,我之前做過的項目就是按百庫百表來做。關于阿里的玩法后面再詳細介紹一下。

          發(fā)現(xiàn)上述評估有問題的話,歡迎留言討論~

          2.4怎么分合適

          Hash取模

          優(yōu)點:經過hash取模之后,分到庫和分到表中的數(shù)據(jù),都是均衡的,所以,不會出現(xiàn)資源傾斜的問題。

          缺點:如果后續(xù)遇到業(yè)務暴增,沒有在我們預估范圍內,則要涉及到數(shù)據(jù)遷移,那就需要重新hash , 遷移數(shù)據(jù),修改路由等等。

          range劃分

          簡單說,就是把數(shù)據(jù)劃分范圍,挨個存儲,存滿一個再存另一個。

          優(yōu)點:不需要數(shù)據(jù)遷移,后續(xù)數(shù)據(jù)即時增長很多也沒問題。

          缺點:數(shù)據(jù)傾斜嚴重,比如上圖,很長一段時間,都會只用到1個庫,幾個表。

          一致性hash

          一致性hash環(huán)的節(jié)點一般按2^32-1來算,但是一般如果業(yè)務ID足夠均衡,則可以降一些節(jié)點,如4096等等,4個庫的話,則均衡的分布在圖上的位置,而數(shù)據(jù)通過hash計算,對應到外環(huán)的虛擬節(jié)點,然后歸屬于真實的庫,對于表也可以同樣處理。或者,直接把表節(jié)點部署在外環(huán)上,直接將數(shù)據(jù)歸屬于表。

          優(yōu)點:更加均勻,并且在需要擴容時,數(shù)據(jù)遷移的量級更小,只需要遷移1/N的數(shù)據(jù)即可。

          缺點:路由算法要復雜,但是對于能得到的好處,這點復雜度就可以忽略了

          小結

          那么,看起來,一致性hash的方法,是比較靠譜的了。但是只是這樣就會對程序員很友好么?

          我不知道其他公司,呆過的某一家公司,的數(shù)據(jù)查詢后臺是純天然的,不帶任何修飾的,想要check下數(shù)據(jù),得拿業(yè)務ID手動計算庫表的位置。沒經歷過的不知道,真的是要煩死了。

          在技術設施方面,還是不得不佩服大公司的投入,阿里給工程師提供的數(shù)據(jù)查詢后臺,其實是一個邏輯庫,你可以用查詢單表的方式去查詢分庫分表,后臺會調用數(shù)據(jù)庫配置平臺的配置,自動計算庫表路由,人性化的很。就算不去計算路由,直接打包查詢多個庫也是很好的,畢竟界面查詢,能有多大并發(fā)呢。

          還是那句話,沒有銀彈,其實除了這幾種方式,還見過不少變種,但都是結合本公司,本業(yè)務的特性進行的改良。

          Part3拆分帶來新的問題

          分區(qū)鍵選取

          分區(qū)鍵要足夠的均勻,比如,用戶表用UID,訂單表可以用UID,也可以用訂單ID,商戶表用商戶ID,問題表用會話ID 等等,總之,一定可以找到業(yè)務上的唯一ID。當然還有一些特殊的分區(qū),比如,日表,月表,則要按時間來分,等等。

          全局唯一主鍵ID

          實際我理解這個就是分布式ID的生成問題,之前寫的一篇分布式ID生成算法,有興趣可以瀏覽下。

          數(shù)據(jù)平滑遷移

          停機發(fā)布:好處是簡單,風險?。蝗秉c是業(yè)務有損。那就看這個損能不能接受了

          平滑遷移:平滑遷移就像是高速上換輪胎,要非常小心謹慎,也更復雜。思路可以類比快手kafka集群的擴容:

          <<< 左右滑動見更多 >>>

          雖然場景不一樣,但是思路使一致的。從某一點開始設置checkpoint , 然后執(zhí)行數(shù)據(jù)雙寫,最后修改路由,刪除舊數(shù)據(jù),完成擴容。

          事務問題

          之前由于數(shù)據(jù)都在一個庫中,所以,只要保證一個本地事務就可以辦到。現(xiàn)在數(shù)據(jù)被分到了多個庫,那么事務怎么保證:

          (1)分布式事務。分布式事務的方式很多,TCC、本地事務表+事務消息、最大努力通知,saga等等。

          (2)程序+業(yè)務邏輯。用業(yè)務邏輯+程序控制的方式,比如,用set化將一個紅包的所有操作都落到同一個庫上,避免了數(shù)據(jù)庫鎖競爭和分布式事務。螞蟻的支付業(yè)務涉及了業(yè)務訂單庫、計收費庫、支付庫、積分庫等等,沒有辦法從業(yè)務邏輯層面進行完全串聯(lián),并且由于金融屬性的強一致要求,采用了非常重的侵入式TCC來保證全局支付事務的一致。

          查詢問題

          之前一個庫就能搞定的join,count等各種聯(lián)合查詢,將不復存在,老老實實調接口在代碼層面實現(xiàn)吧。

          Part4大廠案例,知識回顧擴展

          4.1螞蟻金服的庫表路由規(guī)則

          上文也提到過,螞蟻的分庫分表其實是獨樹一幟的。因為,在螞蟻體系下,需要遵守LDC單元化部署,單元化的路由有用戶ID的倒數(shù)2,3位來決定。加上螞蟻的用戶規(guī)模,基本上大部分的應用都采用了百庫百表類的方式進行(遇到定時任務的超大規(guī)模數(shù)據(jù),還會千庫千表的存在)。用戶請求發(fā)起后的路由規(guī)則和數(shù)據(jù)庫的路由執(zhí)行鏈路簡化如下:而一條訂單的入庫路由規(guī)則可以參考下面的示意圖:[5]

          螞蟻中間件產品介紹

          這樣的機制保證生成的 ID 支持 10 萬億次獲取不重復。

          有人可能會問,這個大的訂單量,一個庫也撐不了多久啊?

          是的,比如之前搞的一個應用,其實是百庫百表+定時數(shù)據(jù)遷移來實現(xiàn)的。業(yè)務數(shù)據(jù)每固定時間進行歷史表遷移。而查詢的時候的庫表路由,都由中間件ZDAL從配置平臺拉取配置來決定,是走歷史庫還是走當前庫。

          4.2大眾點評分庫分表的數(shù)據(jù)遷移

          <<< 左右滑動見更多 >>>

          • 階段一:數(shù)據(jù)雙寫,以老數(shù)據(jù)為準。通過對賬補平差異
          • 階段二:導入歷史數(shù)據(jù),繼續(xù)雙寫,讀切到新數(shù)據(jù)。
          • 階段三:停掉雙寫,刪除老數(shù)據(jù)完成遷移

          4.3淘寶萬億級交易訂單的存儲引擎[6]

          淘寶超級量級下的交易單是怎么解決存儲性能等問題的:可以看到,該方式和上面說過的歷史訂單遷移的方式是如初一轍的。

          Part5總結

          一篇文章不可能窮盡所有知識點,如有遺漏和錯誤,歡迎補充和指正,原創(chuàng)不易,歡迎轉發(fā),留言討論~

          參考資料

          [1]

          日均百萬訂單下的高可用蘇寧拼購系統(tǒng)架構設計.朱羿全: QCon技術峰會分享

          [2]

          支撐億級運單的配運平臺架構實踐.趙玉開: QCon技術峰會分享

          [3]

          大眾點評訂單系統(tǒng)分庫分表實踐: https://tech.meituan.com/2016/11/18/dianping-order-db-sharding.html

          [4]

          如何做好服務拆分: http://dockone.io/article/8241

          [5]

          螞蟻金融中間件產品介紹: https://tech.antfin.com/docs/2/46921

          [6]

          阿里云數(shù)據(jù)庫RDS產品介紹: https://help.aliyun.com/document_detail/161461.html

          瀏覽 142
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  午夜成人性 | 免费无码国产 | 精品国产一区二区三区麻豆传媒 | 天天色天天爽 | 亚洲在线视频免费看 |