分庫分表(1) --- 理論

分庫分表---理論

當一張表的數據達到幾千萬時,查詢一次所花的時間會變長。業界公認MySQL單表容量在 1千萬 如下是最佳狀態,由於這時它的BTREE索引樹高在3~5之間。html

數據切分能夠分爲:垂直切分水平切分mysql

1、垂直切分

垂直切分又能夠分爲: 垂直分庫垂直分表算法

一、垂直分庫

概念 就是根據業務耦合性,將關聯度低的不一樣表存儲在不一樣的數據庫。作法與大系統拆分爲多個小系統相似,按業務分類進行獨立劃分。與"微服務治理"的作法類似,sql

每一個微服務使用單獨的一個數據庫。數據庫

如圖:併發

說明負載均衡

一開始咱們是單體服務,因此只有一個數據庫,全部的表都在這個庫裏。分佈式

後來由於業務需求,單體服務變成微服務治理。因此將以前的一個商品庫,拆分紅多個數據庫。每一個微服務對於一個數據庫。ide

二、垂直分表

概念 把一個表的多個字段分別拆成多個表,通常按字段的冷熱拆分,熱字段一個表,冷字段一個表。從而提高了數據庫性能。函數

如圖:

說明

一開始商品表中包含商品的全部字段,可是咱們發現:

1.商品詳情和商品屬性字段較長2.商品列表的時候咱們是不須要顯示商品詳情和商品屬性信息,只有在點進商品商品的時候纔會展現商品詳情信息

因此能夠考慮把商品詳情和商品屬性單獨切分一張表,提升查詢效率。

三、垂直切分優缺點

優勢

- 解決業務系統層面的耦合,業務清晰
- 與微服務的治理相似,也能對不一樣業務的數據進行分級管理、維護、監控、擴展等
- 高併發場景下,垂直切分必定程度的提高IO、數據庫鏈接數、單機硬件資源的瓶頸

缺點

- 分庫後沒法Join,只能經過接口聚合方式解決,提高了開發的複雜度
- 分庫後分布式事務處理複雜
- 依然存在單表數據量過大的問題(須要水平切分)


2、水平切分

當一個應用難以再細粒度的垂直切分或切分後數據量行數巨大,存在單庫讀寫、存儲性能瓶頸,這時候就須要進行水平切分了。

水平切分也能夠分爲:水平分庫水平分表

一、水平分庫

水平分庫的緣由

上面雖然已經把商品庫分紅3個庫,可是隨着業務的增長一個訂單庫也出現QPS太高,數據庫響應速度來不及,通常mysql單機也就1000左右的QPS,若是超過1000就要考慮分庫。

如圖

二、水平分表

概念 通常咱們一張表的數據不要超過1千萬,若是表數據超過1千萬,而且還在不斷增長數據,那就能夠考慮分表。

如圖

三、垂直切分優缺點

優勢

- 不存在單庫數據量過大、高併發的性能瓶頸,提高系統穩定性和負載能力
- 應用端改造較小,不須要拆分業務模塊

缺點

- 跨分片的事務一致性難以保證
- 跨庫的Join關聯查詢性能較差
- 數據屢次擴展難度和維護量極大


3、數據分片規則

咱們咱們考慮去水平切分表,將一張表水平切分紅多張表,這就涉及到數據分片的規則,比較常見的有:Hash取模分表數值Range分表一致性Hash算法分表

一、Hash取模分表

概念 通常採用Hash取模的切分方式,例如:假設按goods_id分4張表。(goods_id%4 取整肯定表)

優勢

- 數據分片相對比較均勻,不容易出現熱點和併發訪問的瓶頸。

缺點

- 後期分片集羣擴容時,須要遷移舊的數據很難。
- 容易面臨跨分片查詢的複雜問題。好比上例中,若是頻繁用到的查詢條件中不帶goods_id時,將會致使沒法定位數據庫,從而須要同時向4個庫發起查詢,
再在內存中合併數據,取最小集返回給應用,分庫反而成爲拖累。

二、數值Range分表

概念 按照時間區間或ID區間來切分。例如:將goods_id爲1~1000的記錄分到第一個表,1001~2000的分到第二個表,以此類推。

如圖

優勢

- 單表大小可控
- 自然便於水平擴展,後期若是想對整個分片集羣擴容時,只須要添加節點便可,無需對其餘分片的數據進行遷移
- 使用分片字段進行範圍查找時,連續分片可快速定位分片進行快速查詢,有效避免跨分片查詢的問題。

缺點

- 熱點數據成爲性能瓶頸。
例如按時間字段分片,有些分片存儲最近時間段內的數據,可能會被頻繁的讀寫,而有些分片存儲的歷史數據,則不多被查詢

三、一致性Hash算法

一致性Hash算法能很好的解決由於Hash取模而產生的分片集羣擴容時,須要遷移舊的數據的難題。至於具體原理這裏就不詳細說,

能夠參考一篇博客:一致性哈希算法(分庫分表,負載均衡等)


4、分庫分錶帶來的問題

任何事情都有兩面性,分庫分表也不例外,若是採用分庫分表,會引入新的的問題

一、分佈式事務問題

使用分佈式事務中間件解決,具體是經過最終一致性仍是強一致性分佈式事務,看業務需求,這裏就很少說。

二、跨節點關聯查詢 Join 問題

切分以前,咱們能夠經過Join來完成。而切分以後,數據可能分佈在不一樣的節點上,此時Join帶來的問題就比較麻煩了,考慮到性能,儘可能避免使用Join查詢。

解決這個問題的一些方法:

全局表

全局表,也可看作是 "數據字典表",就是系統中全部模塊均可能依賴的一些表,爲了不跨庫Join查詢,能夠將 這類表在每一個數據庫中都保存一份。這些數據一般

不多會進行修改,因此也不擔憂一致性的問題。

字段冗餘

利用空間換時間,爲了性能而避免join查詢。例:訂單表保存userId時候,也將userName冗餘保存一份,這樣查詢訂單詳情時就不須要再去查詢"買家user表"了。

數據組裝

在系統層面,分兩次查詢。第一次查詢的結果集中找出關聯數據id,而後根據id發起第二次請求獲得關聯數據。最後將得到到的數據進行字段拼裝。

三、跨節點分頁、排序、函數問題

跨節點多庫進行查詢時,會出現Limit分頁、Order by排序等問題。分頁須要按照指定字段進行排序,當排序字段就是分片字段時,經過分片規則就比較容易定位到指定的分片;

當排序字段非分片字段時,就變得比較複雜了。須要先在不一樣的分片節點中將數據進行排序並返回,而後將不一樣分片返回的結果集進行彙總和再次排序,最終返回給用戶。

四、全局主鍵避重問題

若是都用主鍵自增確定不合理,若是用UUID那麼沒法作到根據主鍵排序,因此咱們能夠考慮經過雪花ID來做爲數據庫的主鍵,

有關雪花ID能夠參考我以前寫的博客:靜態內部類單例模式實現雪花算法

五、數據遷移問題

採用雙寫的方式,修改代碼,全部涉及到分庫分表的表的增、刪、改的代碼,都要對新庫進行增刪改。同時,再有一個數據抽取服務,不斷地從老庫抽數據,往新庫寫,

邊寫邊按時間比較數據是否是最新的。


參考

一、分庫分表

二、談談分庫分表吧?

三、數據庫分庫分表思路




我相信,不管從此的道路多麼坎坷,只要抓住今天,早晚會在奮鬥中嚐到人生的甘甜。抓住人生中的一分一秒,賽過虛度中的一月一年!(16)
相關文章
相關標籤/搜索