什麼是分庫分表

前言

公司最近在搞服務分離,數據切分方面的東西,因爲單張包裹表的數據量實在是太大,並且還在增長。 之前瞭解過數據庫的分庫分表,讀過幾篇博文,但就只知道個模糊概念, 而且現在回想起來什麼都是模模糊糊的。

今天看了一下午的數據庫分庫分表,看了很多文章,現在做個總結,“摘抄”下來。(但更期待後期的實操) 會從以下幾個方面說起: 

第一部分:實際網站發展過程中面臨的問題。 

第二部分:有哪幾種切分方式,垂直和水平的區別和適用面。

第三部分:目前市面有的一些開源產品,技術,它們的優缺點是什麼。

第四部分:可能是最重要的,爲什麼不建議水平分庫分表!?這能讓你能在規劃前期謹慎的對待,規避掉切分造成的問題。

名詞解釋

庫:database;表:table;分庫分表:sharding

數據庫架構演變

剛開始我們只用單機數據庫就夠了,隨後面對越來越多的請求,我們將數據庫的寫操作和讀操作進行分離, 使用多個從庫副本(Slaver Replication)負責讀,使用主庫(Master)負責寫, 從庫從主庫同步更新數據,保持數據一致。架構上就是數據庫主從同步。 從庫可以水平擴展,所以更多的讀請求不成問題。

但是當用戶量級上來後,寫請求越來越多,該怎麼辦?加一個Master是不能解決問題的, 因爲數據要保存一致性,寫操作需要2個master之間同步,相當於是重複了,而且更加複雜。

這時就需要用到分庫分表(sharding),對寫操作進行切分。

分庫分表前的問題

任何問題都是太大或者太小的問題,我們這裏面對的數據量太大的問題。

用戶請求量太大

因爲單服務器TPS,內存,IO都是有限的。 解決方法:分散請求到多個服務器上; 其實用戶請求和執行一個sql查詢是本質是一樣的,都是請求一個資源,只是用戶請求還會經過網關,路由,http服務器等。

單庫太大

單個數據庫處理能力有限;單庫所在服務器上磁盤空間不足;單庫上操作的IO瓶頸 解決方法:切分成更多更小的庫

單表太大

CRUD都成問題;索引膨脹,查詢超時 解決方法:切分成多個數據集更小的表。

分庫分表的方式方法

一般就是垂直切分和水平切分,這是一種結果集描述的切分方式,是物理空間上的切分。 我們從面臨的問題,開始解決,闡述: 首先是用戶請求量太大,我們就堆機器搞定(這不是本文重點)。

然後是單個庫太大,這時我們要看是因爲表多而導致數據多,還是因爲單張表裏面的數據多。 如果是因爲表多而數據多,使用垂直切分,根據業務切分成不同的庫。

如果是因爲單張表的數據量太大,這時要用水平切分,即把表的數據按某種規則切分成多張表,甚至多個庫上的多張表。 分庫分表的順序應該是先垂直分,後水平分。 因爲垂直分更簡單,更符合我們處理現實世界問題的方式。

垂直拆分

  1. 垂直分表

    也就是“大表拆小表”,基於列字段進行的。一般是表中的字段較多,將不常用的, 數據較大,長度較長(比如text類型字段)的拆分到“擴展表“。 一般是針對那種幾百列的大表,也避免查詢時,數據量太大造成的“跨頁”問題。

  2. 垂直分庫

    垂直分庫針對的是一個系統中的不同業務進行拆分,比如用戶User一個庫,商品Producet一個庫,訂單Order一個庫。 切分後,要放在多個服務器上,而不是一個服務器上。爲什麼? 我們想象一下,一個購物網站對外提供服務,會有用戶,商品,訂單等的CRUD。沒拆分之前, 全部都是落到單一的庫上的,這會讓數據庫的單庫處理能力成爲瓶頸。按垂直分庫後,如果還是放在一個數據庫服務器上, 隨着用戶量增大,這會讓單個數據庫的處理能力成爲瓶頸,還有單個服務器的磁盤空間,內存,tps等非常吃緊。 所以我們要拆分到多個服務器上,這樣上面的問題都解決了,以後也不會面對單機資源問題。

    數據庫業務層面的拆分,和服務的“治理”,“降級”機制類似,也能對不同業務的數據分別的進行管理,維護,監控,擴展等。 數據庫往往最容易成爲應用系統的瓶頸,而數據庫本身屬於“有狀態”的,相對於Web和應用服務器來講,是比較難實現“橫向擴展”的。 數據庫的連接資源比較寶貴且單機處理能力也有限,在高併發場景下,垂直分庫一定程度上能夠突破IO、連接數及單機硬件資源的瓶頸。

水平拆分

  1. 水平分表

    針對數據量巨大的單張表(比如訂單表),按照某種規則(RANGE,HASH取模等),切分到多張表裏面去。 但是這些表還是在同一個庫中,所以庫級別的數據庫操作還是有IO瓶頸。不建議採用。

  2. 水平分庫分表

    將單張表的數據切分到多個服務器上去,每個服務器具有相應的庫與表,只是表中數據集合不同。 水平分庫分表能夠有效的緩解單機和單庫的性能瓶頸和壓力,突破IO、連接數、硬件資源等的瓶頸。

  3. 水平分庫分表切分規則

    1. RANGE

      從0到10000一個表,10001到20000一個表;

    2. HASH取模

      一個商場系統,一般都是將用戶,訂單作爲主表,然後將和它們相關的作爲附表,這樣不會造成跨庫事務之類的問題。 取用戶id,然後hash取模,分配到不同的數據庫上。

    3. 地理區域

      比如按照華東,華南,華北這樣來區分業務,七牛雲應該就是如此。

    4. 時間

      按照時間切分,就是將6個月前,甚至一年前的數據切出去放到另外的一張表,因爲隨着時間流逝,這些表的數據 被查詢的概率變小,所以沒必要和“熱數據”放在一起,這個也是“冷熱數據分離”。

分庫分表後面臨的問題

事務支持

分庫分表後,就成了分佈式事務了。如果依賴數據庫本身的分佈式事務管理功能去執行事務,將付出高昂的性能代價; 如果由應用程序去協助控制,形成程序邏輯上的事務,又會造成編程方面的負擔。

多庫結果集合並(group by,order by)

TODO

跨庫join

TODO 分庫分表後表之間的關聯操作將受到限制,我們無法join位於不同分庫的表,也無法join分表粒度不同的表, 結果原本一次查詢能夠完成的業務,可能需要多次查詢才能完成。 粗略的解決方法: 全局表:基礎數據,所有庫都拷貝一份。 字段冗餘:這樣有些字段就不用join去查詢了。 系統層組裝:分別查詢出所有,然後組裝起來,較複雜。

分庫分表方案產品

目前市面上的分庫分表中間件相對較多,TDDL,Cobar,Mycat。

 

分庫分表原則

分表分庫雖然能解決大表對數據庫系統的壓力,但它並不是萬能的,也有一些不利之處,因此首要問題是,分不分庫,分哪些庫,什麼規則分,分多少分片。

原則一:能不分就不分,1000 萬以內的表,不建議分片,通過合適的索引,讀寫分離等方式,可以很好的解決性能問題。

原則二:分片數量儘量少,分片儘量均勻分佈在多個 DataHost 上,因爲一個查詢 SQL 跨分片越多,則總體性能越差,雖然要好於所有數據在一個分片的結果,只在必要的時候進行擴容,增加分片數量。

原則三:分片規則需要慎重選擇,分片規則的選擇,需要考慮數據的增長模式,數據的訪問模式,分片關聯性問題,以及分片擴容問題,最近的分片策略爲範圍分片,枚舉分片,一致性 Hash 分片,這幾種分片都有利於擴容。

原則四:儘量不要在一個事務中的 SQL 跨越多個分片,分佈式事務一直是個不好處理的問題。

原則五:查詢條件儘量優化,儘量避免 Select * 的方式,大量數據結果集下,會消耗大量帶寬和 CPU 資源,查詢儘量避免返回大量結果集,並且儘量爲頻繁使用的查詢語句建立索引。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章