Sharding-jdbc 分庫分表專題內容(一)

一、ShardingSphere背景

ShardingSphere是一套開源的分佈式數據庫中間件解決方案組成的生態圈,由以下部分組成。

  1. Sharding-JDBC - 提供標準化的數據分片
  2. Sharding-Proxy - 分佈式事務
  3. Sharding-Sidecar(計劃中)- 數據庫治理功能

可適用於如Java同構、異構語言、容器、雲原生等各種多樣化的應用場景。

二、概念 & 功能

2.1 背景

傳統的將數據集中存儲至單一數據節點的解決方案,在性能、可用性和運維成本這三方面已經難於滿足互聯網的海量數據場景。

在傳統的關係型數據庫無法滿足互聯網場景需要的情況下,將數據存儲至原生支持分佈式的NoSQL的嘗試越來越多。 但NoSQL對SQL的不兼容性以及生態圈的不完善,使得它們在與關係型數據庫的博弈中始終無法完成致命一擊,而關係型數據庫的地位卻依然不可撼動。

數據分片指按照某個維度將存放在單一數據庫中的數據分散地存放至多個數據庫或表中以達到提升性能瓶頸以及可用性的效果。
分庫分表均可以有效的避免由數據量超過可承受閾值而產生的查詢瓶頸。 除此之外,分庫還能夠用於有效的分散對數據庫單點的訪問量;分表雖然無法緩解數據庫壓力,但卻能夠提供儘量將分佈式事務轉化爲本地事務的可能,一旦涉及到跨庫的更新操作,分佈式事務往往會使問題變得複雜。 使用多主多從的分片方式,可以有效的避免數據單點,從而提升數據架構的可用性。
數據分片的拆分方式又分爲垂直分片水平分片

2.2 垂直分片

按照業務拆分的方式稱爲垂直分片,又稱爲縱向拆分,它的核心理念是專庫專用。 在拆分之前,一個數據庫由多個數據表構成,每個表對應着不同的業務。而拆分之後,則是按照業務將表進行歸類,分佈到不同的數據庫中,從而將壓力分散至不同的數據庫。

下圖展示了根據業務需要,將用戶表和訂單表垂直分片到不同的數據庫的方案。
在這裏插入圖片描述
使用垂直切分方案的主要優點如下:

  1. 拆分後業務清晰,符合微服務的總體設計理念;
  2. 子系統之間的整合與擴展相對容易;
  3. 按照不同的業務類型,將不同的庫表放在不同的數據庫服務器上,便於管理;
  4. 根據業務數據的“冷”、“熱”狀態,採用不同的緩存和數據庫模式設計方案;

垂直切分的缺點如下:

  1. 跨庫的Join查詢,需要使用不同子系統的API接口讀取後在內存中完成關聯查詢,提高系統複雜度
  2. 如果某一種類型的業務呈現爆發式地增長,該業務對應的庫表還是會存在單DB的IO讀寫的瓶頸問題,從這一點來說垂直切分並未從根本解決單庫單表數據量過大的問題;
  3. 存在跨庫事務的一致性問題,解決起來比較麻煩,當然也可以採用分佈式事務來解決;

2.3 水平分片

水平分片又稱爲橫向拆分。 相對於垂直分片,它不再將數據根據業務邏輯分類,而是通過某個字段(或某幾個字段),根據某種規則將數據分散至多個庫或表中,每個分片僅包含數據的一部分。 例如:根據主鍵分片,偶數主鍵的記錄放入0庫(或表),奇數主鍵的記錄放入1庫(或表),如下圖所示。
在這裏插入圖片描述
使用水平切分方案的主要優點如下:

  1. 單庫單表的數據容量可以維持在一個量級,有助於提高業務SQL的執行效率和系統性能;
  2. 不管是利用ShardingJdbc組件還是MyCat框架,業務系統的應用層涉及改造得都較少,只需要根據實際的業務情況來設計數據分片的路由規則即可;
  3. 可以提高業務系統的穩定性和負載能力;

使用水平切分方案的主要缺點如下:

  1. 數據水平切分後,分佈在多庫多表中,跨庫Join查詢比較複雜;
  2. 分片數據的一致性較爲難保證;
  3. 對於歷史數據的遷移和數據庫的擴容需要較大的維護工作量;

三、Sharding-JDBC核心概念

3.1 基本概念

定位爲輕量級Java框架,在Java的JDBC層提供的額外服務。 它使用客戶端直連數據庫,以jar包形式提供服務,無需額外部署和依賴,可理解爲增強版的JDBC驅動,完全兼容JDBC和各種ORM框架。

  • 適用於任何基於Java的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。
  • 基於任何第三方的數據庫連接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP等。
  • 支持任意實現JDBC規範的數據庫。目前支持MySQL,Oracle,SQLServer和PostgreSQL。

3.2 核心概念

邏輯表(LogicTable):進行水平拆分的時候同一類型(邏輯、數據結構相同)的表的總稱。例:訂單數據根據主鍵尾數拆分爲10張表,分別是t_order_0到t_order_9,他們的邏輯表名爲t_order。
真實表(ActualTable):在分片的數據庫中真實存在的物理表。即上個示例中的t_order_0到t_order_9。
數據節點(DataNode):數據分片的最小單元。由數據源名稱和數據表組成,例:ds_0.t_order_0。
動態表(DynamicTable):邏輯表和物理表不一定需要在配置規則中靜態配置。如,按照日期分片的場景,物理表的名稱隨着時間的推移會產生變化。
綁定表(BindingTable):指分片規則一致的主表和子表。例如:t_order表和t_order_item表,均按照order_id分片,則此兩張表互爲綁定表關係。綁定表之間的多表關聯查詢不會出現笛卡爾積關聯,關聯查詢效率將大大提升。舉例說明,如果SQL爲:
廣播表: 指所有的分片數據源中都存在的表,表結構和表中的數據在每個數據庫中均完全一致。適用於數據量不大且需要與海量數據的表進行關聯查詢的場景,例如:字典表。
邏輯索引:某些數據庫(如:PostgreSQL)不允許同一個庫存在名稱相同索引,某些數據庫(如:MySQL)則允許只要同一個表中不存在名稱相同的索引即可。 邏輯索引用於同一個庫不允許出現相同索引名稱的分表場景,需要將同庫不同表的索引名稱改寫爲索引名 + 表名,改寫之前的索引名稱成爲邏輯索引。
分片鍵(ShardingColumn):分片字段用於將數據庫(表)水平拆分的字段,支持單字段及多字段分片。例如上例中的order_id。
分片算法(ShardingAlgorithm):進行水平拆分時採用的算法,分片算法需要應用方開發者自行實現,可實現的靈活度非常高。目前提供4種分片算法。由於分片算法和業務實現緊密相關,因此並未提供內置分片算法,而是通過分片策略將各種場景提煉出來,提供更高層級的抽象,並提供接口讓應用開發者自行實現分片算法。

3.3 分片

3.3.1 分片算法

通過分片算法將數據分片,支持通過=、>=、<=、>、<、BETWEEN和IN分片。分片算法需要應用方開發者自行實現,可實現的靈活度非常高。

1.精確分片算法
對應PreciseShardingAlgorithm,用於處理使用單一鍵作爲分片鍵的=與IN進行分片的場景。需要配合StandardShardingStrategy使用。
2.範圍分片算法
對應RangeShardingAlgorithm,用於處理使用單一鍵作爲分片鍵的BETWEEN AND、>、<、>=、<=進行分片的場景。需要配合StandardShardingStrategy使用。
3.複合分片算法
對應ComplexKeysShardingAlgorithm,用於處理使用多鍵作爲分片鍵進行分片的場景,包含多個分片鍵的邏輯較複雜,需要應用開發者自行處理其中的複雜度。需要配合ComplexShardingStrategy使用。
4.Hint分片算法
對應HintShardingAlgorithm,用於處理使用Hint行分片的場景。需要配合HintShardingStrategy使用。

3.3.2 分片策略

分片策略:可用於分片操作的是分片鍵 + 分片算法
1. 標準分片策略
對應StandardShardingStrategy。提供對SQL語句中的=, >, <, >=, <=, IN和BETWEEN AND的分片操作支持。StandardShardingStrategy只支持單分片鍵,提供PreciseShardingAlgorithm和RangeShardingAlgorithm兩個分片算法。PreciseShardingAlgorithm是必選的,用於處理=和IN的分片。RangeShardingAlgorithm是可選的,用於處理BETWEEN AND, >, <, >=, <=分片,如果不配置RangeShardingAlgorithm,SQL中的BETWEEN AND將按照全庫路由處理。
2. 複合分片策略
對應ComplexShardingStrategy。複合分片策略。提供對SQL語句中的=, >, <, >=, <=, IN和BETWEEN AND的分片操作支持。ComplexShardingStrategy支持多分片鍵,由於多分片鍵之間的關係複雜,因此並未進行過多的封裝,而是直接將分片鍵值組合以及分片操作符透傳至分片算法,完全由應用開發者實現,提供最大的靈活度。
3. 行表達式分片策略
對應InlineShardingStrategy。使用Groovy的表達式,提供對SQL語句中的=和IN的分片操作支持,只支持單分片鍵。對於簡單的分片算法,可以通過簡單的配置使用,從而避免繁瑣的Java代碼開發,如: t_user_$->{u_id % 8} 表示t_user表根據u_id模8,而分成8張表,表名稱爲t_user_0到t_user_7。
4. Hint分片策略
對應HintShardingStrategy。通過Hint而非SQL解析的方式分片的策略。
5. 不分片策略
對應NoneShardingStrategy。不分片的策略。

3.3 核心架構


在這裏插入圖片描述
由圖可知,在sql執行過程中需要經過幾個過程:
例如現在有一條查詢語句:

select * from t_user where id=10

進行了分庫分表操作,2個庫ds0,ds1,採用的分片鍵爲id,邏輯表爲t_user,真實表爲t_user_0、t_user_1兩張表,分庫、分表算法爲均爲取餘(%2)。
sql解析:通過解析sql語句提取分片鍵列與值進行分片,例如比較符 =、in 、between and,及查詢的表等。
sql改寫:根據解析結果,及採用的分片邏輯改寫sql,上例經過sql改寫後,真實語句爲:

select * from t_user_0 where id=10

sql路由:找到sql需要去哪個庫、哪個表執行語句,上例sql根據採用的策略可以得到將在ds0庫,t_user_0表執行語句。
sql執行:執行改寫後的sql。
結果歸併:當我們執行某些複雜語句時,sql可能會在多個庫、多個表中執行,sql分別對應執行後會對結果集進行歸併操作,得到最終的結果。

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