來自 GitChat 做者:沈劍
更多IT技術分享,盡在微信公衆號:GitChat 技術雜談html
本篇講義將以「訂單中心」爲例,介紹「多key」類業務,隨着數據量的逐步增大,數據庫性能顯著下降,數據庫水平切分相關的架構實踐。web
所謂的「多key」,是指一條元數據中,有多個屬性上存在前臺在線查詢需求。算法
訂單中心業務分析數據庫
訂單中心是一個很是常見的「多key」業務,主要提供訂單的查詢與修改的服務,其核心元數據爲:
Order(oid, buyer_uid, seller_uid, time, money, detail…);其中:微信
數據庫設計上,通常來講在業務初期,單庫單表就可以搞定這個需求,典型的架構設計爲:架構
隨着訂單量的愈來愈大,數據庫須要進行水平切分,因爲存在多個key上的查詢需求,用哪一個字段進行切分,成了須要解決的關鍵技術問題:併發
buyer_uid
和seller_uid
上的查詢則須要遍歷多庫。buyer_uid
或seller_uid
來切分,其餘屬性上的查詢則須要遍歷多庫。總之,很難有一個徹底之策,在展開技術方案以前,先一塊兒梳理梳理查詢需求。異步
在進行架構討論以前,先來對業務進行簡要分析,看哪些屬性上有查詢需求。數據庫設計
前臺訪問,最典型的有三類需求:
前臺訪問的特色:吞吐量大,服務要求高可用,用戶對訂單的訪問一致性要求高,商家對訂單的訪問一致性要求相對較低,能夠接受必定時間的延時。
後臺訪問,根據產品、運營需求,訪問模式各異:
按照時間,架構,商品,詳情來進行查詢。
運營側的查詢基本上是批量分頁的查詢,因爲是內部系統,訪問量很低,對可用性的要求不高,對一致性的要求也沒這麼嚴格,容許秒級甚至十秒級別的查詢延時。
這兩類不一樣的業務需求,應該使用什麼樣的架構方案來解決呢?
若是前臺業務和後臺業務公用一批服務和一個數據庫,有可能致使,因爲後臺的「少數幾個請求」的「批量查詢」的「低效」訪問,致使數據庫的cpu偶爾瞬時100%,影響前臺正經常使用戶的訪問(例如,訂單查詢超時)。
前臺與後臺訪問的查詢需求不一樣,對系統的要求也不同,故應該二者解耦,實施「前臺與後臺分離」的架構設計。
前臺業務架構不變,站點訪問,服務分層,數據庫水平切分。
後臺業務需求則抽取獨立的web/service/db來支持,解除系統之間的耦合,對於「業務複雜」「併發量低」「無需高可用」「能接受必定延時」的後臺業務:
解決了後臺業務的訪問需求,問題轉化爲,前臺的oid,buyer_uid,seller_uid如何來進行數據庫水平切分呢?
多個維度的查詢較爲複雜,對於複雜系統設計,能夠逐步簡化。
訂單中心,假設沒有seller_uid
上的查詢需求,而只有oid和buyer_uid
上的查詢需求,就蛻化爲一個「1對多」的業務場景,對於「1對多」的業務,水平切分應該使用「基因法」。
再次回顧一下,什麼是分庫基因?
經過buyer_uid
分庫,假設分爲16個庫,採用buyer_uid
%16的方式來進行數據庫路由,所謂的模16,其本質是buyer_uid
的最後4個bit決定這行數據落在哪一個庫上,這4個bit,就是分庫基因。
也再次回顧一下,什麼是基因法分庫?
在訂單數據oid生成時,oid末端加入分庫基因,讓同一個buyer_uid
下的全部訂單都含有相同基因,落在同一個分庫上。
如上圖所示,buyer_uid=666的用戶下了一個訂單:
經過這種方法保證,同一個用戶下的全部訂單oid,都落在同一個庫上,oid的最後4個bit都相同,因而:
訂單中心,假設沒有oid上的查詢需求,而只有buyer_uid和seller_uid上的查詢需求,就蛻化爲一個「多對多」的業務場景,對於「多對多」的業務,水平切分應該使用「數據冗餘法」。
如上圖所示:
buyer_uid
分庫,seller庫經過seller_uid
分庫,前者知足oid和buyer_uid
的查詢需求,後者知足seller_uid
的查詢需求。數據冗餘的方法有不少種:
無論哪一種方案,由於兩步操做不能保證原子性,總有出現數據不一致的可能,高吞吐分佈式事務是業內還沒有解決的難題,此時的架構優化方向,並非徹底保證數據的一致,而是儘早的發現不一致,並修復不一致。
最終一致性,是高吞吐互聯網業務一致性的經常使用實踐。保證數據最終一致性的方案有三種:
這些方案細節在「多對多」業務水平拆分的文章裏詳細展開分析過,便再也不贅述。
經過上述分析:
seller_uid
,「多key」業務會蛻化爲「1對多」業務,此時應該使用「基因法」分庫:使用buyer_uid
分庫,在oid中加入分庫基因buyer_uid
和seller_uid
來分別分庫,冗餘數據,知足不一樣屬性上的查詢需求複雜難題的解決,都是一個化繁爲簡,逐步擊破的過程。
對於像訂單中心同樣複雜的「多key」類業務,在數據量較大,須要對數據庫進行水平切分時,對於後臺需求,採用「前臺與後臺分離」的架構設計方法:
對於前臺需求,化繁爲簡的設計思路,將「多key」類業務,分解爲「1對多」類業務和「多對多」類業務分別解決:
buyer_uid
分庫,在oid中加入分庫基因,同時知足oid和buyer_uid
上的查詢需求buyer_uid
和seller_uid
來分別分庫,冗餘數據,知足buyer_uid
和seller_uid
上的查詢需求數據冗餘會帶來一致性問題,高吞吐互聯網業務,要想徹底保證事務一致性很難,常見的實踐是最終一致性。
任何脫離業務的架構設計都是耍流氓,共勉。
水平切分是一個頗有意思的話題,感謝堅持半年訂閱的小夥伴們,下個月最後一章,爲答謝大夥的支持,可免費訂閱(gitchat不容許免費,設定爲1元),歡迎你們訂閱。
也歡迎你們持續關注本次系列話題的最後一場Chat:《後語:除了水平切分,數據庫架構設計還常常遇到哪些問題》。
本文首發於GitChat,未經受權不得轉載,轉載需與GitChat聯繫。