GitChat · 架構 | 從訂單中心開始,聊「多KEY」類業務數據庫水平切分架構實踐

來自 GitChat 做者:沈劍
更多IT技術分享,盡在微信公衆號:GitChat 技術雜談html

進入 GitChat 閱讀原文git

前言

本篇講義將以「訂單中心」爲例,介紹「多key」類業務,隨着數據量的逐步增大,數據庫性能顯著下降,數據庫水平切分相關的架構實踐。web

1、什麼是「多key」類業務

所謂的「多key」,是指一條元數據中,有多個屬性上存在前臺在線查詢需求。算法

訂單中心業務分析數據庫

訂單中心是一個很是常見的「多key」業務,主要提供訂單的查詢與修改的服務,其核心元數據爲:
Order(oid, buyer_uid, seller_uid, time, money, detail…);其中:微信

  1. oid爲訂單ID,主鍵
  2. buyer_uid爲買家uid
  3. seller_uid爲賣家uid
  4. time, money, detail, …等爲訂單屬性

數據庫設計上,通常來講在業務初期,單庫單表就可以搞定這個需求,典型的架構設計爲:架構

enter image description here

  1. order-center:訂單中心服務,對調用者提供友好的RPC接口。
  2. order-db:對訂單進行數據存儲。

隨着訂單量的愈來愈大,數據庫須要進行水平切分,因爲存在多個key上的查詢需求,用哪一個字段進行切分,成了須要解決的關鍵技術問題:併發

  1. 若是用oid來切分,buyer_uidseller_uid上的查詢則須要遍歷多庫。
  2. 若是用buyer_uidseller_uid來切分,其餘屬性上的查詢則須要遍歷多庫。

總之,很難有一個徹底之策,在展開技術方案以前,先一塊兒梳理梳理查詢需求。異步

2、訂單中心屬性查詢需求分析

在進行架構討論以前,先來對業務進行簡要分析,看哪些屬性上有查詢需求。數據庫設計

前臺訪問,最典型的有三類需求:

  • 訂單實體查詢:經過oid查詢訂單實體,90%流量屬於這類需求。
  • 用戶訂單列表查詢:經過buyer_uid分頁查詢用戶歷史訂單列表,9%流量屬於這類需求。
  • 商家訂單列表查詢:經過seller_uid分頁查詢商家歷史訂單列表,1%流量屬於這類需求。

前臺訪問的特色:吞吐量大,服務要求高可用,用戶對訂單的訪問一致性要求高,商家對訂單的訪問一致性要求相對較低,能夠接受必定時間的延時。

後臺訪問,根據產品、運營需求,訪問模式各異:

按照時間,架構,商品,詳情來進行查詢。

運營側的查詢基本上是批量分頁的查詢,因爲是內部系統,訪問量很低,對可用性的要求不高,對一致性的要求也沒這麼嚴格,容許秒級甚至十秒級別的查詢延時。

這兩類不一樣的業務需求,應該使用什麼樣的架構方案來解決呢?

3、前臺與後臺分離的架構設計

若是前臺業務和後臺業務公用一批服務和一個數據庫,有可能致使,因爲後臺的「少數幾個請求」的「批量查詢」的「低效」訪問,致使數據庫的cpu偶爾瞬時100%,影響前臺正經常使用戶的訪問(例如,訂單查詢超時)。

前臺與後臺訪問的查詢需求不一樣,對系統的要求也不同,故應該二者解耦,實施「前臺與後臺分離」的架構設計。

enter image description here

前臺業務架構不變,站點訪問,服務分層,數據庫水平切分。

後臺業務需求則抽取獨立的web/service/db來支持,解除系統之間的耦合,對於「業務複雜」「併發量低」「無需高可用」「能接受必定延時」的後臺業務:

  • 能夠去掉service層,在運營後臺web層經過dao直接訪問數據層。
  • 能夠不須要反向代理,不須要集羣冗餘。
  • 能夠經過MQ或者線下異步同步數據,犧牲一些數據的實時性。
  • 可使用更契合大量數據容許接受更高延時的「索引外置」或者「HIVE」的設計方案。

解決了後臺業務的訪問需求,問題轉化爲,前臺的oid,buyer_uid,seller_uid如何來進行數據庫水平切分呢?

多個維度的查詢較爲複雜,對於複雜系統設計,能夠逐步簡化。

4、假設沒有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下的全部訂單都含有相同基因,落在同一個分庫上。

enter image description here

如上圖所示,buyer_uid=666的用戶下了一個訂單:

  • 使用buyer_uid%16分庫,決定這行數據要插入到哪一個庫中。
  • 分庫基因是buyer_uid的最後4個bit,即1010。
  • 在生成訂單標識oid時,先使用一種分佈式ID生成算法生成前60bit(上圖中綠色部分)。
  • 將分庫基因加入到oid的最後4個bit(上圖中粉色部分),拼裝成最終64bit的訂單oid(上圖中藍色部分)。

經過這種方法保證,同一個用戶下的全部訂單oid,都落在同一個庫上,oid的最後4個bit都相同,因而:

  • 經過buyer_uid%16可以定位到庫。
  • 經過oid%16也能定位到庫。

5、假設沒有oid

訂單中心,假設沒有oid上的查詢需求,而只有buyer_uid和seller_uid上的查詢需求,就蛻化爲一個「多對多」的業務場景,對於「多對多」的業務,水平切分應該使用「數據冗餘法」。

enter image description here

如上圖所示:

  1. 當有訂單生成時,經過buyer_uid分庫,oid中融入分庫基因,寫入DB-buyer庫。
  2. 經過線下異步的方式,經過binlog+canal,將數據冗餘到DB-seller庫中。
  3. buyer庫經過buyer_uid分庫,seller庫經過seller_uid分庫,前者知足oid和buyer_uid的查詢需求,後者知足seller_uid的查詢需求。

數據冗餘的方法有不少種:

  1. 服務同步雙寫。
  2. 服務異步雙寫。
  3. 線下異步雙寫(上圖所示,是線下異步雙寫)。

無論哪一種方案,由於兩步操做不能保證原子性,總有出現數據不一致的可能,高吞吐分佈式事務是業內還沒有解決的難題,此時的架構優化方向,並非徹底保證數據的一致,而是儘早的發現不一致,並修復不一致。

最終一致性,是高吞吐互聯網業務一致性的經常使用實踐。保證數據最終一致性的方案有三種:

  1. 冗餘數據全量定時掃描。
  2. 冗餘數據增量日誌掃描。
  3. 冗餘數據線上消息實時檢測。

這些方案細節在「多對多」業務水平拆分的文章裏詳細展開分析過,便再也不贅述。

6、oid/buyer_uid/seller_uid同時存在

經過上述分析:

  • 若是沒有seller_uid,「多key」業務會蛻化爲「1對多」業務,此時應該使用「基因法」分庫:使用buyer_uid分庫,在oid中加入分庫基因
  • 若是沒有oid,「多key」業務會蛻化爲「多對多」業務,此時應該使用「數據冗餘法」分庫:使用buyer_uidseller_uid來分別分庫,冗餘數據,知足不一樣屬性上的查詢需求
  • 若是oid/buyer_uid/seller_uid同時存在,可使用上述兩種方案的綜合方案,來解決「多key」業務的數據庫水平切分難題。

7、總結

複雜難題的解決,都是一個化繁爲簡,逐步擊破的過程。

對於像訂單中心同樣複雜的「多key」類業務,在數據量較大,須要對數據庫進行水平切分時,對於後臺需求,採用「前臺與後臺分離」的架構設計方法

  • 前臺、後臺系統web/service/db分離解耦,避免後臺低效查詢引起前臺查詢抖動。
  • 採用前臺與後臺數據冗餘的設計方式,分別知足兩側的需求。
  • 採用「外置索引」(例如ES搜索系統)或者「大數據處理」(例如HIVE)來知足後臺變態的查詢需求。

對於前臺需求,化繁爲簡的設計思路,將「多key」類業務,分解爲「1對多」類業務和「多對多」類業務分別解決:

  • 使用「基因法」,解決「1對多」分庫需求:使用buyer_uid分庫,在oid中加入分庫基因,同時知足oid和buyer_uid上的查詢需求
  • 使用「數據冗餘法」,解決「多對多」分庫需求:使用buyer_uidseller_uid來分別分庫,冗餘數據,知足buyer_uidseller_uid上的查詢需求
  • 若是oid/buyer_uid/seller_uid同時存在,可使用上述兩種方案的綜合方案,來解決「多key」業務的數據庫水平切分難題

數據冗餘會帶來一致性問題,高吞吐互聯網業務,要想徹底保證事務一致性很難,常見的實踐是最終一致性。

任何脫離業務的架構設計都是耍流氓,共勉。

水平切分是一個頗有意思的話題,感謝堅持半年訂閱的小夥伴們,下個月最後一章,爲答謝大夥的支持,可免費訂閱(gitchat不容許免費,設定爲1元),歡迎你們訂閱。

也歡迎你們持續關注本次系列話題的最後一場Chat:《後語:除了水平切分,數據庫架構設計還常常遇到哪些問題》


本文首發於GitChat,未經受權不得轉載,轉載需與GitChat聯繫。


實錄

實錄:《沈劍:「多KEY」類業務數據庫水平切分架構解析》


彩蛋

圖片描述

相關文章
相關標籤/搜索