1. 程式人生 > >【幹貨】數據庫分庫分表基礎和實踐

【幹貨】數據庫分庫分表基礎和實踐

ima 邏輯關系 部分 平分 range cto database 單個 ron

數據庫架構的演變
在業務數據量比較少的時代,我們使用單機數據庫就能滿足業務使用,隨著業務請求量越來越多,數據庫中的數據量快速增加,這時單機數據庫已經不能滿足業務的性能要求,數據庫主從復制架構隨之應運而生。

主從復制是將數據庫寫操作和讀操作進行分離,使用多個只讀實例(slaver replication)負責處理讀請求,主實例(master)負責處理寫請求,只讀實例通過復制主實例的數據來保持與主實例的數據一致性。由於只讀實例可以水平擴展,所以更多的讀請求不成問題,隨著雲計算、大數據時代的到來,事情並沒有完美的得以解決,當寫請求越來越多,主實例的寫請求變成主要的性能瓶頸。

如何解決上述問題?如果僅僅通過增加一個主實例來分擔寫請求,寫操作如何在兩個主實例之間同步來保證數據一致性,如何避免雙寫,問題會變的更加復雜。這時就需要用到分庫分表(sharding),對寫操作進行切分來解決,如圖1所示:

技術分享圖片
圖1:典型的讀寫分離和分庫分表

華為雲中間件產品DDM(Distributed Database Middleware)作為RDS的前置分布式數據庫訪問服務,徹底解決了數據庫的擴展性問題,對應用透明地實現海量數據的高並發訪問,實現了讀寫分離和分庫分表。

數據分片的實現方案
數據分片的實現方案可分為應用層分片和中間件分片,這兩種實現方案的特點如圖2所示:
技術分享圖片
圖2:應用層分片和中間件分片

DDM作為一款優秀的分布式數據庫中間件產品,實現了讀寫分離和數據分片功能,使用DDM來分庫分表,應用0改動,對應用完全透明。

分庫分表的切分方式
數據的切分(Sharding)根據其切分規則的類型,可以分為兩種切分模式。一種是按照不同的表(或者Schema)來切分到不同的數據庫(主機)之上,這種切分方式可以稱之為數據的垂直(縱向)切分;另外一種則是根據表中的數據的邏輯關系,將同一個表中的數據按照某種條件拆分到多臺數據庫(主機)上面,這種切分稱之為數據的水平(橫向)切分。

垂直切分最大特點就是規則簡單,實施也更為方便,尤其適合各業務之間的耦合度非常低,相互影響很小,業務邏輯非常清晰的系統。在這種系統中,可以很容易做到將不同業務模塊所使用的表分拆到不同的數據庫中。根據不同的表來進行拆分,對應用程序的影響也更小,拆分規則也會比較簡單清晰。

水平切分於垂直切分相比,相對來說稍微復雜一些。因為要將同一個表中的不同數據拆分到不同的數據庫中,對於應用程序來說,拆分規則本身比根據表名來拆分更為復雜,後期的數據維護也會更為復雜一些。

具體而言,如果單個庫太大,這時我們要看是因為表多而導致數據多,還是因為單張表裏面的數據多。如果是因為表多而數據多,使用垂直切分,根據業務切分成不同的庫。如果是因為單張表的數據量太大,這時要用水平切分,即把表的數據按某種規則切分成多張表,甚至多個庫上的多張表。分庫分表的順序應該是先垂直分,後水平分。因為垂直分更簡單,更符合我們處理現實世界問題的方式。

水平切分
相對於垂直拆分,水平拆分不是將表做分類,而是按照某個字段的某種規則來分散到多個庫之中,每個表中包含一部分數據。簡單來說,我們可以將數據的水平切分理解為是按照數據行的切分,就是將表中的某些行切分到一個數據庫,而另外的某些行又切分到其他的數據庫中,如圖3:
技術分享圖片
圖3:水平切分

水平切分的優點
1、拆分規則抽象好,join操作基本可以數據庫做。
2、不存在單庫大數據,高並發的性能瓶頸。
3、應用端改造較少。
4、 提高了系統的穩定性跟負載能力。

水平切分的缺點
1、拆分規則難以抽象。
2、分片事務一致性難以解決。
3、數據多次擴展難度跟維護量極大。
4、跨庫join性能較差。

水平切分的典型分片規則
1、HASH取模
例如:取用戶id,然後hash取模,分配到不同的數據庫上。
2、RANGE
例如:從0到10000一個表,10001到20000一個表。
3、時間
按照時間切分,例如:將6個月前,甚至一年前的數據切出去放到另外的一張表,因為隨著時間流逝,這些表的數據被查詢的概率變小,所以沒必要和”熱數據“放在一起,這個也是“冷熱數據分離”。
切分原則一般是根據業務找到適合的切分規則分散到不同的庫,如圖4,根據用戶ID取模作為切分規則。
技術分享圖片
圖4:根據userid取模進行切分

垂直切分
一個數據庫由很多表的構成,每個表對應著不同的業務,垂直切分是指按照業務將表進行分類,分布到不同的數據庫上面,這樣也就將數據或者說壓力分擔到不同的庫上面,如圖5:
技術分享圖片
圖5:垂直切分

垂直切分的優點
1、數據維護簡單。
2、拆分後業務清晰,拆分規則明確。
3、系統之間整合或擴展容易。

垂直切分的缺點
1、事務處理復雜。
2、部分業務表無法join,只能通過接口方式解決,提高了系統復雜度。
3、受每種業務不同的限制存在單庫性能瓶頸,不易數據擴展跟性能提高。

由於垂直切分是按照業務的分類將表分散到不同的庫,所以有些業務表會過於龐大,存在單庫讀寫與存儲瓶頸,所以就需要水平拆分來做解決。

切分原則
由於數據切分後數據Join的難度,在此也分享一下數據切分的經驗:
第一原則:能不切分盡量不要切分。
第二原則:如果要切分一定要選擇合適的切分規則,提前規劃好。
第三原則:數據切分盡量通過數據冗余或表分組(Table Group)來降低跨庫Join的可能。
第四原則:由於數據庫中間件對數據Join實現的優劣難以把握,而且實現高性能難度極大,業務讀取盡量少使用多表Join。

分庫分表後的問題和應對策略
分庫分表主要用於應對當前互聯網常見的兩個場景:海量數據和高並發。然而,分庫分表是一把雙刃劍,雖然很好的應對海量數據和高並發對數據庫的沖擊和壓力,但也提高了系統的復雜度和維護成本,帶來一些問題。

1、事務支持
在分庫分表後,就成為分布式事務了,如何保證數據的一致性成為一個必須面對的問題。一般情況下,使存儲數據盡可能達到用戶一致,保證系統經過一段較短的時間的自我恢復和修正,數據最終達到一致。

2、分頁與排序問題
一般情況下,列表分頁時需要按照指定字段進行排序。在單庫單表的情況下,分頁和排序也是非常容易的。但是,隨著分庫與分表的演變,也會遇到跨庫排序和跨表排序問題。為了最終結果的準確性,需要在不同的分表中將數據進行排序並返回,並將不同分表返回的結果集進行匯總和再次排序,最後再返回給用戶。

3、表關聯問題
在單庫單表的情況下,聯合查詢是非常容易的。但是,隨著分庫與分表的演變,聯合查詢就遇到跨庫關聯的問題。粗略的解決方法:ER分片:子表的記錄與所關聯的父表記錄存放在同一個數據分片上。全局表:基礎數據,所有庫都拷貝一份。字段冗余:這樣有些字段就不用join去查詢了。ShareJoin:是一個簡單的跨分片join,目前支持2個表的join,原理就是解析SQL語句,拆分成單表的SQL語句執行,然後把各個節點的數據匯集。

4、分布式全局唯一ID
在單庫單表的情況下,直接使用數據庫自增特性來生成主鍵ID,這樣確實比較簡單。在分庫分表的環境中,數據分布在不同的分表上,不能再借助數據庫自增長特性,需要使用全局唯一ID。

分庫分表案例
某稅務核心征管系統,全國34個省國/地稅,電子稅務局15省格局。

技術路徑:核心征管 + 納稅服務 業務應用分布式上雲改造。

業務挑戰
1、數據查詢時間3-5秒,響應速度慢嚴重影響體驗
當前業務邏輯大量放在數據庫層,一個辦稅業務的事務邊界過大(40條SQL語句),涉及以“申報”、“發票”大表為主的多張表關聯事務操作,導致業務查詢響應速度慢。
2、億級數據快速的增長,挑戰業務性能瓶頸
省級稅務局,辦稅高峰期承載百萬級用戶並發量,3000-5000TPS。現網分析得到數據:核心征管庫近1000張表,其中“申報”、“發票”業務表數據量大、增長快,是主要瓶頸表;發票綜合信息:每省10億級條記錄,每年千萬到億條記錄級別增量;申報信息表:億級記錄數據量。

解決方案
1、垂直分庫、微服務分解數據庫壓力,降低單業務sql數
基於微服務將大事務拆解為異步小事務,業務邏輯從數據庫層面剝離。拆分主庫數據,將大表垂直拆分到多個數據庫中,一個業務40條SQL縮減到20條SQL,達到分解數據庫壓力的目的。
2、數據分片支撐海量數據增長,線性提升業務處理速度
單表億級記錄以納稅人作為拆分鍵,拆分到RDS-MySQL 的128個分片上。實現支撐海量數據的存儲。拆分後數據庫設計簡潔、簡單,數據庫的表之間不設外鍵,不寫觸發器,不寫存儲過程,實現數據庫記錄的水平擴展。
3、讀寫分離提升查詢性能
DDM自動實現讀寫分離,透明地完成寫操作和讀操作的分發,應用程序無需做特殊的改動和處理邏輯。寫操作分發到RDS主實例,讀操作自動分發到RDS的多個讀實例上,這樣寫操作不會影響讀操作的並發,讀並發業務增長時只需要按需增加只讀實例即可。

企業受益
1、使用了DDM之後,輕松突破原來的性能瓶頸,一次業務操作,原來需要3到5秒,現在只需要1秒。
2、讀寫操作通過DDM的自動讀寫分離,在不改動業務情況下,輕松提升了整體的讀寫並發能力。

【幹貨】數據庫分庫分表基礎和實踐