分庫與分表設計

2021-09-29 07:43:42 字數 4016 閱讀 3989

垂直(縱向)切分:把單一的表拆分成多個表,並分散到不同的資料庫(主機)上。

水平(橫向)切分:根據表中資料的邏輯關係,將同乙個表中的資料按照某種條件拆分到多台資料庫(主機)上。

乙個資料庫由多個表構成,每個表對應不同的業務,垂直切分是指按照業務將表進行分類,將其分布到不同的資料庫上,這樣就將資料分擔到了不同的庫上(專庫專用)。

優點如下:

1)、拆分後業務清晰,拆分規則明確。

2)、系統之間進行整合或擴充套件很容易。

3)、按照成本、應用的等級、應用的型別等將表放到不同的機器上,便於管理。

4)、便於實現動靜分離、冷熱分離的資料庫表的設計模式。

5)、資料維護簡單。

缺點如下:

1)、部分業務表無法關聯(join),只能通過介面方式解決,提高了系統的複雜度。

2)、受每種業務的不同限制,存在單庫效能瓶頸,不易進行資料擴充套件和提公升效能。

3)、事務處理複雜。

與垂直切分對比,水平切分不是將表進行分類,而是將其按照某個欄位的某種規則分散到多個庫中,在每個表中包含一部分資料,所有表加起來就是全量的資料。

簡單來說,我們可以將對資料的水平切分理解為按照資料行進行切分,就是將表中的某些行切分到乙個資料庫表中,而將其他行切分到其他資料庫表中。

這種切分方式根據單錶的資料量的規模來切分,保證單錶的容量不會太大,從而保證了單錶的查詢等處理能力,例如將使用者的資訊表拆分成user1、user2等,表結構是完全一樣的。我們通常根據某些特定的規則來劃分表,比如根據使用者的id來取模劃分。

優點如下:

1)、單庫單錶的資料保持在一定的量級,有助於效能的提高。

2)、切分的表的結構相同,應用層改造較少,只需要增加路由規則即可。

3)、提高了系統的穩定性和負載能力。

缺點如下:

1)、切分後,資料是分散的,很難利用資料庫的join操作,跨庫join效能較差。

2)、拆分規則難以抽象。

3)、分片事務的一致性難以解決。

4)、資料擴容的難度和維護量極大。

對資料切片有不同的切片維度,可以參考mycat提供的切片方式(見本書3.4節),這裡只介紹兩種最常用的切片維度。

1)按照雜湊切片

對資料的某個字段求雜湊,再除以分片總數後取模,取模後相同的資料為乙個分片,這樣的將資料分成多個分片的方法叫作雜湊分片。

2)按照時間切片

與按照雜湊切片不同,這種方式是按照時間的範圍將資料分布到不同的分片上的,例如,我們可以將交易資料按照月進行切片,或者按照季度進行切片,由交易資料的多少來決定按照什麼樣的時間週期對資料進行切片。

存在分布式事務的問題。

存在跨節點join的問題。

存在跨節點合併排序、分頁的問題。

存在多資料來源管理的問題。

前面介紹到水平分表策略歸納總結為

隨機分表和連續分表

兩種情況。連續分表有可能存在

資料熱點

的問題,有些表可能會被頻繁地查詢從而造成較大壓力,熱資料的表就成為了整個庫的瓶頸,而有些表可能存的是歷史資料,很少需要被查詢到。連續分表的另外乙個好處在於比較容易,不需要考慮遷移舊的資料,只需要新增分表就可以自動擴容。

隨機分表

的資料相對比較均勻,不容易出現熱點和併發訪問的瓶頸。但是,

分表擴充套件需要遷移舊的資料

。針對於水平分表的設計至關重要,需要評估中短期內業務的增長速度,對當前的資料量進行容量規劃,綜合成本因素,推算出大概需要多少分片。對於資料遷移的問題,一般做法是

通過程式先讀出資料

,然後按照指定的分表策略再將資料寫入到各個分表中。

在單庫單錶的情況下,聯合查詢是非常容易的。但是,隨著分庫與分表的演變,聯合查詢就遇到跨庫關聯和跨表關係問題。在設計之初就應該盡量避免聯合查詢,可以

通過程式中進行拼裝,或者通過反正規化化設計

進行規避。

一般情況下,列表分頁時需要按照指定字段進行排序。在單庫單錶的情況下,分頁和排序也是非常容易的。但是,隨著分庫與分表的演變,也會遇到跨庫排序和跨表排序問題。為了最終結果的準確性,需要在不同的分表中將資料進行排序並返回,並

將不同分表返回的結果集進行彙總和再次排序

,最後再返回給使用者。

方法一:全域性視野法(1

)將order by time offset x limit y

,改寫成

order by time offset 0 limit x+y (

2)服務層對得到的

n*(x+y)

條資料進行記憶體排序,記憶體排序後再取偏移量x後的

y條記錄

這種方法

隨著翻頁的進行,效能越來越低。

方法二:業務折衷法-禁止跳頁查詢(1

)用正常的方法取得第一頁資料,並得到第一頁記錄的

time_max (

2)每次翻頁,將

order by time offset x limit y

,改寫成

order by time where time>$time_max limit y

以保證每次只返回一頁資料,效能為常量。

方法三:二次查詢法(1

)將order by time offset x limit y

,改寫成

order by time offset x/n limit y (

2)找到最小值

time_min (

3)between

二次查詢,

order by time between $time_min and $time_i_max (

4)設定虛擬

time_min

,找到time_min

在各個分庫的

offset

,從而得到

time_min

在全域性的

offset (

5)得到了

time_min

在全域性的

offset

,自然得到了全域性的

offset x limit y

隨著分庫與分表的演變,一定會遇到分布式事務問題,那麼如何保證資料的一致性就成為乙個必須面對的問題。目前,分布式事務並沒有很好的解決方案,難以滿足資料強一致性,一般情況下,

使儲存資料盡可能達到使用者一致,保證系統經過一段較短的時間的自我恢復和修正,資料最終達到一致

。在單庫單錶的情況下,直接使用資料庫自增特性來生成主鍵id,這樣確實比較簡單。在分庫分表的環境中,資料分布在不同的分表上,不能再借助資料庫自增長特性。需要使用全域性唯一 id,例如 uuid、guid等。關於如何選擇合適的全域性唯一 id,我會在後面的章節中進行介紹。

業界方案:

uuid:通過唯一識別碼16個位元組128位的長數字。

優點:**實現簡單、不占用寬頻、資料遷移不受影響

缺點:無序、無法保證趨勢遞增(要求3)字元儲存、傳輸、查詢慢、不可讀

snowflake雪花演算法

國外的twitter分布式下id生成演算法

1bit+41bit+10bit+10+bit=62bit

高位隨機+毫秒數+機器碼(資料中心+機器id)+10的流水好

國內:保證資料的唯一性就行了idc機房

優點:**實現簡單、不占用寬頻、資料遷移不受影響、低位趨勢遞增

缺點:強以來時鐘(多台伺服器時間一定要一樣)、無序無法保證趨勢遞增redis:

縮減版本、有關業務**沒有包含到裡頭、redis方案

優點:不依賴資料、靈活方便、效能優於資料庫的、沒有單點故障(高可用)

缺點:需要占用網路資源、效能要比本地生成慢、需要增加外掛程式

分庫與分表主要用於應對當前網際網路常見的兩個場景:

海量資料

和高併發。然而,分庫與分表是一把雙刃劍,雖然很好的應對海量資料和高併發對資料庫的衝擊和壓力,但是卻提高的系統的複雜度和維護成本。

因此,我的建議:需要結合實際需求,不宜過度設計,在專案一開始不採用分庫與分表設計,而是隨著業務的增長,在無法繼續優化的情況下,再考慮分庫與分表提高系統的效能。

mysql分表分庫實現 MySql分表分庫思路

一.資料庫瓶頸 1.1io瓶頸 第一種 磁碟讀io瓶頸,熱點資料太多,資料庫快取放不下,每次查詢時會產生大量的io 分庫和垂直分表 第二種 網路io瓶頸,請求的資料太多,網路頻寬不夠 分庫 1.2cpu瓶頸 第一種 sql問題,如sql中包含join,group by,order by,非索引字段條...

MySQL範圍分表分庫 mysql 分表分庫策略

唯一id的生成 下面列舉幾種常見的唯一id生成方案,需要滿足兩大核心需求 1.全域性唯一 2趨勢有序 1.用資料庫的auto increment 自增id 來生成,每次通過寫入資料庫一條記錄,利用資料庫id自增的特性獲取唯一,有序的id。優點 使用資料庫原有的功能,相對簡單 能夠保證唯一 能夠保證遞...

mysql 分庫分表實戰 MySQL分庫分表實戰

為什麼要分庫分表 在大型 中,當使用者量以及使用者產生的業務資料量達到單庫單錶效能極限時,為了支撐業務可持續發展,對於重要的核心業務必然要進行分庫分表來儲存業務資料。對於非核心業務產生的大量資料,例如爬蟲爬取的資訊,論壇產生的資料等,可以考慮把資料儲存在像mongodb這樣的nosql儲存裡面,這些...