推薦收藏|資料庫架構一次搞定(適合2-6年工程師)

架構師修行手冊發表於2023-04-21


源頭

上上週有一個讀者問我,資料庫架構設計到底是啥?

結合職業生涯中做過DBA,並且這幾年也在持續關注資料庫,果斷安排!

資料庫設計要設計啥?

  1. 只要涉及到業務肯定都會需要
  • 依據業務模式,設計庫結構、表結構
  • 依據訪問模式,設計索引結構

這裡值得一提的是,關於庫表設計有些公司會交給DBA來負責,並最佳化讀寫

其實這一部分更需要業務工程師和業務架構師來進行

因為無論是庫、表還是索引結構都和業務的架構設計息息相關

  1. 那除了庫表、索引結構還需要設計什麼?

一般理解下設計了庫表、索引就不影響業務開發了,真的是這樣嗎?

隨著資料上漲,在高可用容災、讀寫效能、一致性、擴充套件性等多個方面都會面臨著瓶頸

這更應該是資料庫設計中尤為關注的

  • 高可用

現在的業務架構中,基本都會做叢集,這時候業務層解決了單點異常的問題

但此時資料庫掛了影響會進一步放大,尤其產生堆積以後,恢復時間會拉長

  • 讀效能

資料庫和大資料架構的訪問模式類似,都是讀多寫少

讀請求一般對應著業務的搜尋,爬蟲,瀏覽、列表,詳情

寫請求一般對應加減、核銷庫存,付款,下單

根據絕大部分網際網路業務的經驗,資料庫往往最先成為系統的瓶頸

而在資料庫的讀和寫上,往往讀會率先成為瓶頸點

如果為了增加資料庫的讀效能

無論是加從庫,加快取還是其他方式,在業務的架構設計時,需要考慮這點

  • 一致性

剛才提到了,加從庫增加資料庫讀請求的上限

但是增加了從庫後,可能會導致延遲增加,造成主從資料的不一致

加快取也是一樣,在正常讀庫之前增加了快取層

但會導致快取和資料庫資料不一致

因此做資料庫冗餘、做快取高可用,資料不一致如何解決也是資料庫架構設計重要課題

  • 擴充套件性

當我們在使用資料庫時,隨著業務體量增加,經常會面臨如下幾個問題:

  • 資料量大如何擴充套件?
  • 寫效能擴充套件?
  • 讀效能擴充套件?

典型的資料庫架構

1. 單使用者單例項推薦收藏|資料庫架構一次搞定(適合2-6年工程師)

單使用者單例項其實沒啥專門講的,業務前期所有表都在一個庫裡

不過多表join的場景會出現拆庫拆不動,因為都在一個db例項上

如果要拆庫改動的話涉及到業務改造

假設單庫若干張表,實際上只要加了uuid屬性

並且設計好索引,效能也基本滿足小業務需求

業務的訂單表和庫存表如果不在一個庫中,就一定會涉及到分散式事務

這時才是一個大坑,如果你不瞭解分散式事務,可以看看之前寫的文章《啥?分散式啥?啥事務?》


2. 分組(group) + 複製(replication)推薦收藏|資料庫架構一次搞定(適合2-6年工程師)

  • 2.1 分組解決什麼問題?

    原本的讀由單例項擴充套件到3例項,讀效能增加

    讀上可容忍2個例項掛掉,進一步擴充套件讀高可用

    寫單點擴充套件到寫高可用,但這裡實際上仍舊只有Master1個例項提供寫

    此時如果Master例項掛掉,Slave例項會提升成主來提供寫

    在切換過程中,寫上有秒級別的不可用

    • 寫高可用有一定擴充套件
    • 擴充套件讀高可用
    • 擴充套件讀效能
  • 2.2 分組帶來什麼問題?

    由於使用Master-Slave架構,透過binlog方式進行主從同步

    主從之間會有一定延遲,資料敏感度高的業務依舊只能讀Master節點

    • 主從延遲問題
  • 2.3 分組沒有解決什麼問題?-

    由於只有Master例項提供寫能力,實際依舊是單點,只不過可以儘快可以把Slave提成Master

    儘管此時有多個例項,但仍舊是單資料儲存

    分組+複製使用資源來換取讀效能和高可用的擴充套件

    實際上這種架構也是算是分散式系統,關於分散式系統CAP沙盤推演,可以看看之前寫的《拜託!這才是分散式系統CAP的正確開啟方式!》

    • 沒有解決資料儲存的問題
    • 寫高可用不徹底

3. 分片(sharding)+ 路由(router)

推薦收藏|資料庫架構一次搞定(適合2-6年工程師)
  • 3.1 分片解決了什麼問題?

    原有是單資料儲存,依託分片架構,可以進行資料儲存的水平擴充套件

    由於從單例項過渡到了多例項,每個例項都能提供讀能力

    原有架構只有1個例項可提供寫,分片後多例項都可以提供寫能力

    • 寫效能擴充套件
    • 讀效能擴充套件
    • 擴充套件資料儲存
  • 3.2 分片帶來了什麼問題?

    寫從單例項擴充套件到了多例項,原有的SQL會產生相容性問題

    跨庫Join查詢,原本直接寫SQL就能實現的邏輯,現在會產生變化

    比如求個資料的Min,這時只拿一個庫的資料,結果顯然是不準確的

    解法1: DB層保持不變,業務層改造進行多例項資料聚合的讀取;

    但涉及到業務邏輯改變,有比較高的改造成本,需要和業務進行拉手

    解法2: 業務層保持不變,在中介軟體層進行join邏輯重寫,

    解析業務SQL的join邏輯,轉譯到多例項場景

    使用分片路由的架構,因為增加了路由策略層,複雜度會增加很多

    不同的路由規則會導致新的問題產生,常見的路由分片策略如下:

    <1> 雜湊(Hash)路由

    一致性雜湊、雜湊取模或雜湊桶,是目前最主流和常見的方案

    雜湊路由解決了資料例項之間負載不均衡的問題

    但例項擴充套件的過程,會導致資料遷移,進而對讀寫效能產生一定影響

    一致性Hash相關的內容,可以看看之前寫的《求錘得錘,你要的一致性hash來了(上)[附程式碼]》和 《求錘得錘,你要的一致性hash來了(下)[附程式碼]》

    Hash取模相關的內容,可以看看之前寫的《3行程式碼實現Hash路由分片(附程式碼)》

    Hash桶相關內容,可以看看之前寫的《原來這個“桶”也能路由分片》


    <2> 範圍(Range)路由

    除了雜湊路由外,比較常見策略的還有範圍路由

    他解決了Hash路由的模型限制,支援了範圍查詢

    擴充套件起來比較方便,不需要大幅度遷移資料

    典型的範圍分片一般會使用LSM樹,以此來提升批次寫效率

    但範圍分片經常會受業務的邏輯影響導致讀寫負載不均衡

    也就是我們經常說的熱點情況

    比如APP註冊新使用者活躍度高,讀寫請求會遠高於活躍度低的老使用者

    再比如微博文章庫,vip賬號的資料儲存往往會是普通賬號的N倍

    範圍分片相關的內容,可以看看之前寫的《震驚!全網唯一 直擊範圍分片本質[適用HBase、Tidb等]》

    • 帶來路由規則的問題
    • 犧牲掉sql的特性
  • 3.3 分片沒有解決什麼問題?

    分片的架構寫例項拆分後,依舊存在寫單點的問題

    每個例項中都是獨立的資料表,如果一個例項掛掉

    即使中介軟體層做路由切換,歷史資料也無法讀取

    並且還會造成新、老資料的不一致。

    • 沒有解決高可用問題

4. 分片(Sharding)+分組(Group)

推薦收藏|資料庫架構一次搞定(適合2-6年工程師)

4.1 分組+分片解決什麼問題?

  • 寫擴充套件性問題
  • 讀擴充套件性問題
  • 資料擴充套件問題
  • 讀+寫高可用問題

分組+分片的架構,目前在一些公司也有應用

解決了讀寫擴充套件性、高可用和資料擴充套件問題

優勢相關的細節在上面章節都有,這裡就不細說了

4.2 分組+分片帶來什麼問題?

整套架構很美好,關鍵的資料庫架構問題基本都有解了

但這套架構成熟度比較高,意味著複雜度也很高

需要業務、中介軟體、資料庫層面的同步拉手和對齊

由於涉及到改造,在演變過程中對業務衝擊是很大的

因此改造帶來的收益和風險需要仔細評估,切記拍腦袋


5. 垂直拆分

推薦收藏|資料庫架構一次搞定(適合2-6年工程師)

垂直拆分是一種和業務緊密相連的資料庫架構

原來的業務表User儲存在單庫下

垂直拆分後User表分裂成User.Base + User.Extend表

分別儲存在兩個庫下

  • 5.1 垂直拆分解決了什麼問題?

    • 解決效能問題
  1. 訪問頻繁和短的資料放到基礎表,不頻繁的放到擴充套件表上
  2. MySQL buffer能夠快取更多頻繁的使用的資料,非列式資料都可以快取在記憶體中,比如布林型的欄位,年齡、性別、狀態等1-8位元組的欄位,讓資料更多落到buffer裡,提升訪問效率,反之比如自我介紹類的,char/varchar型別,一般都幾十、上百位元組,這類則如果放在自我buffer裡,則快取的內容會大大減少,這類不頻繁使用的讀寫磁碟更合適
  • 5.2 垂直拆分帶來了什麼問題?

    垂直拆分和分片得到的結果是一樣的

    區別在於是業務層做還是資料庫層面來做

    由於表分裂成兩個表分別儲存單庫

    因此帶來了和單獨分片一樣的問題

    需要SQL1拆2,在業務層面需要改在,進行聚合

    因此使用垂直拆分+分組的架構,也是一個比較好的架構

    垂直拆分是一個業務工程,如果對業務理解不夠是玩不轉的

    但現狀是DBA通常面向的是整個公司,並不僅僅支撐某個業務

    深入瞭解業務的細節邏輯,顯然是難度非常大的

    因此垂直拆分需要業務架構師或者研發深度參與

    • 和業務需要緊密配合
    • SQL拆分問題

    怎樣選擇合適的資料庫架構

    上面我們聊了很多資料庫架構

    那麼如何選型其實是一個非常重要的問題

    在我看來做資料庫架構設計2個關鍵點:

    1. 知道業務想要什麼?切忌自嗨

    對於底層基礎服務來說,如何解決業務最痛的問題是尤為重要的

    做Inf實際很苦,畢竟不直接產生經濟價值

    只能透過幫助業務實現商業成功來體現我們的價值

    因此如果業務想要效能,給業務整個高可用方案顯然是不恰當的

    “賣”給業務一個他想吃的蘋果,和業務同頻共振,這樣才能前進

    1. 知道自己有什麼?切忌短視

    脫離經濟基礎,而大談上層建築是非常可怕的

    知道業務想要什麼之後,我們一定還要知道自己處於一個什麼階段

    對資料庫現狀要有清晰的認知,還涉及到資源投入、短中長規劃等等

    比如目前業務很穩定,並沒有很多需求,只是日常的一些支援

    但業務的變化通常非常迅猛,如果不想資料庫成為業務的瓶頸

    我們還是得做點什麼,比如預研新技術、新架構等等

    這時需要做Inf長期的規劃,用規劃倒逼出里程碑和路徑



    來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70027824/viewspace-2947342/,如需轉載,請註明出處,否則將追究法律責任。

    相關文章