數據庫架構的演變html
在業務數據量比較少的時代,咱們使用單機數據庫就能知足業務使用,隨着業務請求量愈來愈多,數據庫中的數據量快速增長,這時單機數據庫已經不能知足業務的性能要求,數據庫主從複製架構隨之應運而生。sql
主從複製是將數據庫寫操做和讀操做進行分離,使用多個只讀實例(slaver replication)負責處理讀請求,主實例(master)負責處理寫請求,只讀實例經過複製主實例的數據來保持與主實例的數據一致性。因爲只讀實例能夠水平擴展,因此更多的讀請求不成問題,隨着雲計算、大數據時代的到來,事情並無完美的得以解決,當寫請求愈來愈多,主實例的寫請求變成主要的性能瓶頸。數據庫
如何解決上述問題?若是僅僅經過增長一個主實例來分擔寫請求,寫操做如何在兩個主實例之間同步來保證數據一致性,如何避免雙寫,問題會變的更加複雜。這時就須要用到分庫分表(sharding),對寫操做進行切分來解決,如圖1所示:架構
圖1:典型的讀寫分離和分庫分表併發
華爲雲中間件產品DDM(Distributed Database Middleware)做爲RDS的前置分佈式數據庫訪問服務,完全解決了數據庫的擴展性問題,對應用透明地實現海量數據的高併發訪問,實現了讀寫分離和分庫分表。異步
數據分片的實現方案數據庫設計
數據分片的實現方案可分爲應用層分片和中間件分片,這兩種實現方案的特色如圖2所示:分佈式
圖2:應用層分片和中間件分片微服務
DDM做爲一款優秀的分佈式數據庫中間件產品,實現了讀寫分離和數據分片功能,使用DDM來分庫分表,應用0改動,對應用徹底透明。高併發
分庫分表的切分方式
數據的切分(Sharding)根據其切分規則的類型,能夠分爲兩種切分模式。一種是按照不一樣的表(或者Schema)來切分到不一樣的數據庫(主機)之上,這種切分方式能夠稱之爲數據的垂直(縱向)切分;另一種則是根據表中的數據的邏輯關係,將同一個表中的數據按照某種條件拆分到多臺數據庫(主機)上面,這種切分稱之爲數據的水平(橫向)切分。
垂直切分最大特色就是規則簡單,實施也更爲方便,尤爲適合各業務之間的耦合度很是低,相互影響很小,業務邏輯很是清晰的系統。在這種系統中,能夠很容易作到將不一樣業務模塊所使用的表分拆到不一樣的數據庫中。根據不一樣的表來進行拆分,對應用程序的影響也更小,拆分規則也會比較簡單清晰。
水平切分於垂直切分相比,相對來講稍微複雜一些。由於要將同一個表中的不一樣數據拆分到不一樣的數據庫中,對於應用程序來講,拆分規則自己比根據表名來拆分更爲複雜,後期的數據維護也會更爲複雜一些。
具體而言,若是單個庫太大,這時咱們要看是由於表多而致使數據多,仍是由於單張表裏面的數據多。若是是由於表多而數據多,使用垂直切分,根據業務切分紅不一樣的庫。若是是由於單張表的數據量太大,這時要用水平切分,即把表的數據按某種規則切分紅多張表,甚至多個庫上的多張表。分庫分表的順序應該是先垂直分,後水平分。由於垂直分更簡單,更符合咱們處理現實世界問題的方式。
水平切分
相對於垂直拆分,水平拆分不是將表作分類,而是按照某個字段的某種規則來分散到多個庫之中,每一個表中包含一部分數據。簡單來講,咱們能夠將數據的水平切分理解爲是按照數據行的切分,就是將表中的某些行切分到一個數據庫,而另外的某些行又切分到其餘的數據庫中,如圖3:
圖3:水平切分
水平切分的優勢
一、拆分規則抽象好,join操做基本能夠數據庫作。
二、不存在單庫大數據,高併發的性能瓶頸。
三、應用端改造較少。
四、 提升了系統的穩定性跟負載能力。
水平切分的缺點
一、拆分規則難以抽象。
二、分片事務一致性難以解決。
三、數據屢次擴展難度跟維護量極大。
四、跨庫join性能較差。
水平切分的典型分片規則
一、HASH取模
例如:取用戶id,而後hash取模,分配到不一樣的數據庫上。
二、RANGE
例如:從0到10000一個表,10001到20000一個表。
三、時間
按照時間切分,例如:將6個月前,甚至一年前的數據切出去放到另外的一張表,由於隨着時間流逝,這些表的數據被查詢的機率變小,因此不必和」熱數據「放在一塊兒,這個也是「冷熱數據分離」。
切分原則通常是根據業務找到適合的切分規則分散到不一樣的庫,如圖4,根據用戶ID取模做爲切分規則。
圖4:根據userid取模進行切分
垂直切分
一個數據庫由不少表的構成,每一個表對應着不一樣的業務,垂直切分是指按照業務將表進行分類,分佈到不一樣的數據庫上面,這樣也就將數據或者說壓力分擔到不一樣的庫上面,如圖5:
圖5:垂直切分
垂直切分的優勢
一、數據維護簡單。
二、拆分後業務清晰,拆分規則明確。
三、系統之間整合或擴展容易。
垂直切分的缺點
一、事務處理複雜。
二、部分業務表沒法join,只能經過接口方式解決,提升了系統複雜度。
三、受每種業務不一樣的限制存在單庫性能瓶頸,不易數據擴展跟性能提升。
因爲垂直切分是按照業務的分類將表分散到不一樣的庫,因此有些業務表會過於龐大,存在單庫讀寫與存儲瓶頸,因此就須要水平拆分來作解決。
切分原則
因爲數據切分後數據Join的難度,在此也分享一下數據切分的經驗:
第一原則:能不切分儘可能不要切分。
第二原則:若是要切分必定要選擇合適的切分規則,提早規劃好。
第三原則:數據切分儘可能經過數據冗餘或表分組(Table Group)來下降跨庫Join的可能。
第四原則:因爲數據庫中間件對數據Join實現的優劣難以把握,並且實現高性能難度極大,業務讀取儘可能少使用多表Join。
分庫分表後的問題和應對策略
分庫分表主要用於應對當前互聯網常見的兩個場景:海量數據和高併發。然而,分庫分表是一把雙刃劍,雖然很好的應對海量數據和高併發對數據庫的衝擊和壓力,但也提升了系統的複雜度和維護成本,帶來一些問題。
一、事務支持
在分庫分表後,就成爲分佈式事務了,如何保證數據的一致性成爲一個必須面對的問題。通常狀況下,使存儲數據儘量達到用戶一致,保證系統通過一段較短的時間的自我恢復和修正,數據最終達到一致。
二、分頁與排序問題
通常狀況下,列表分頁時須要按照指定字段進行排序。在單庫單表的狀況下,分頁和排序也是很是容易的。可是,隨着分庫與分表的演變,也會遇到跨庫排序和跨表排序問題。爲了最終結果的準確性,須要在不一樣的分表中將數據進行排序並返回,並將不一樣分表返回的結果集進行彙總和再次排序,最後再返回給用戶。
三、表關聯問題
在單庫單表的狀況下,聯合查詢是很是容易的。可是,隨着分庫與分表的演變,聯合查詢就遇到跨庫關聯的問題。粗略的解決方法:ER分片:子表的記錄與所關聯的父表記錄存放在同一個數據分片上。全局表:基礎數據,全部庫都拷貝一份。字段冗餘:這樣有些字段就不用join去查詢了。ShareJoin:是一個簡單的跨分片join,目前支持2個表的join,原理就是解析SQL語句,拆分紅單表的SQL語句執行,而後把各個節點的數據聚集。
四、分佈式全局惟一ID
在單庫單表的狀況下,直接使用數據庫自增特性來生成主鍵ID,這樣確實比較簡單。在分庫分表的環境中,數據分佈在不一樣的分表上,不能再借助數據庫自增加特性,須要使用全局惟一ID。
分庫分表案例
某稅務核心徵管系統,全國34個省國/地稅,電子稅務局15省格局。
技術路徑:核心徵管 + 納稅服務 業務應用分佈式上雲改造。
業務挑戰
一、數據查詢時間3-5秒,響應速度慢嚴重影響體驗
當前業務邏輯大量放在數據庫層,一個辦稅業務的事務邊界過大(40條SQL語句),涉及以「申報」等大表爲主的多張表關聯事務操做,致使業務查詢響應速度慢。
二、億級數據快速的增加,挑戰業務性能瓶頸
省級稅務局,辦稅高峯期承載百萬級用戶併發量,3000-5000TPS。現網分析獲得數據:核心徵管庫近1000張表,其中「申報」等業務表數據量大、增加快,是主要瓶頸表;票據綜合信息:每省10億級條記錄,每一年千萬到億條記錄級別增量;申報信息表:億級記錄數據量。
解決方案
一、垂直分庫、微服務分解數據庫壓力,下降單業務sql數
基於微服務將大事務拆解爲異步小事務,業務邏輯從數據庫層面剝離。拆分主庫數據,將大表垂直拆分到多個數據庫中,一個業務40條SQL縮減到20條SQL,達到分解數據庫壓力的目的。
二、數據分片支撐海量數據增加,線性提高業務處理速度
單表億級記錄以納稅人做爲拆分鍵,拆分到RDS-MySQL 的128個分片上。實現支撐海量數據的存儲。拆分後數據庫設計簡潔、簡單,數據庫的表之間不設外鍵,不寫觸發器,不寫存儲過程,實現數據庫記錄的水平擴展。
三、讀寫分離提高查詢性能
DDM自動實現讀寫分離,透明地完成寫操做和讀操做的分發,應用程序無需作特殊的改動和處理邏輯。寫操做分發到RDS主實例,讀操做自動分發到RDS的多個讀實例上,這樣寫操做不會影響讀操做的併發,讀併發業務增加時只須要按需增長只讀實例便可。
企業受益
一、使用了DDM以後,輕鬆突破原來的性能瓶頸,一次業務操做,原來須要3到5秒,如今只須要1秒。
二、讀寫操做經過DDM的自動讀寫分離,在不改動業務狀況下,輕鬆提高了總體的讀寫併發能力。