sharding-jdbc常用的分片場景政策:
取餘/取模分片:優點-均勻存放資料,缺點-擴容非常困難
按照範圍分片:比較好擴容,資料分布不均勻,可能造成資源浪費
按照時間分片:比較容易将熱點資料區分出來
按照枚舉值分片:例如按照地區分片
按照目标字段字首指定進行分區:自定義規則
sharding-jdbc核心概念:
sql
邏輯表:水準拆分的資料庫(表)的相同邏輯和資料結構表的總稱。例:訂單資料根據主鍵尾數拆分為 10 張表,分别是到
t_order_0
,他們的邏輯表名為
t_order_9
t_order
。
真實表:在分片的資料庫中真實存在的實體表。即上個邏輯表的例子中的
到
t_order_0
t_order_9
。
資料節點:資料分片的最小單元。由資料源名稱和資料表組成,例:
ds_0.t_order_0
。
綁定表:指分片規則一緻的主表和子表。例如:
表和
t_order
表,均按照
t_order_item
分片,則此兩張表互為綁定表關系。綁定表之間的多表關聯查詢不會出現笛卡爾積關聯,關聯查詢效率将大大提升。舉例說明,如果 SQL 為:
order_id
在不配置綁定表關系時,假設分片鍵SELECT i.* FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);
将數值 10 路由至第 0 片,将數值 11 路由至第 1 片,那麼路由後的 SQL 應該為 4 條,它們呈現為笛卡爾積:
order_id
在配置綁定表關系後,路由的 SQL 應該為 2 條:SELECT i.* FROM t_order_0 o JOIN t_order_item_0 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11); SELECT i.* FROM t_order_0 o JOIN t_order_item_1 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11); SELECT i.* FROM t_order_1 o JOIN t_order_item_0 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11); SELECT i.* FROM t_order_1 o JOIN t_order_item_1 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);
其中SELECT i.* FROM t_order_0 o JOIN t_order_item_0 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11); SELECT i.* FROM t_order_1 o JOIN t_order_item_1 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);
在 FROM 的最左側,ShardingSphere 将會以它作為整個綁定表的主表。 所有路由計算将會隻使用主表的政策,那麼
t_order
表的分片計算将會使用
t_order_item
t_order
的條件。故綁定表之間的分區鍵要完全相同。
廣播表:指所有的分片資料源中都存在的表,表結構和表中的資料在每個資料庫中均完全一緻。适用于資料量不大且需要與海量資料的表進行關聯查詢的場景,例如:字典表。
分片
分⽚鍵 : ⽤于分⽚的資料庫字段,是将資料庫(表)⽔平拆分的關鍵字段。例:将訂單表中的訂單主鍵的尾數取模分⽚,則訂單主鍵為分⽚字段。SQL 中如果⽆分⽚字段,将執⾏全路由,性能較差。除了對單分⽚字段的 ⽀持, Apache ShardingSphere 也⽀持根據多個字段進⾏分⽚。 分⽚算法 : 通過分⽚算法将資料分⽚,⽀持通過 = 、 >= 、 <= 、 > 、 < 、 BETWEEN 和 IN 分⽚。分⽚算法需要應⽤⽅開 發者⾃⾏實作,可實作的靈活度⾮常⾼。 ⽬前提供 4 種分⽚算法。由于分⽚算法和業務實作緊密相關,是以并未提供内置分⽚算法,而是通過分 ⽚政策将各種場景提煉出來,提供更⾼層級的抽象,并提供接口讓應⽤開發者⾃⾏實作分⽚算法。
• 标準分⽚算法 :對應 StandardShardingAlgorithm,⽤于處理使⽤單⼀鍵作為分⽚鍵的 =、IN、BETWEEN AND、>、<、>=、 <= 進⾏分⽚的場景。需要配合 StandardShardingStrategy 使⽤。
• 複合分⽚算法 :對應 ComplexKeysShardingAlgorithm,⽤于處理使⽤多鍵作為分⽚鍵進⾏分⽚的場景,包含多個分⽚鍵的邏輯較複雜,需要應⽤開發者⾃⾏處理其中的複雜度。需要配合 ComplexShardingStrategy 使⽤。
• Hint 分⽚算法 :對應 HintShardingAlgorithm,⽤于處理使⽤ Hint ⾏分⽚的場景。需要配合 HintShardingStrategy 使⽤。
分⽚政策: 包含分⽚鍵和分⽚算法,由于分⽚算法的獨⽴性,将其獨⽴抽離。真正可⽤于分⽚操作的是分⽚鍵 + 分 ⽚算法,也就是分⽚政策。⽬前提供 5 種分⽚政策。
• 标準分⽚政策 :對應 StandardShardingStrategy。提供對 SQ L 語句中的 =, >, <, >=, <=, IN 和 BETWEEN AND 的分⽚操作 ⽀持。StandardShardingStrategy 隻⽀持單分⽚鍵,提供 PreciseShardingAlgorithm 和 RangeShardingAlgorithm兩個分⽚算法。PreciseShardingAlgorithm是必選的,⽤于處理=和IN的分⽚。RangeShardingAlgorithm 是可選的,⽤于處理 BETWEEN AND, >, <, >=, <= 分⽚,如果不配置 RangeShardingAlgorithm, SQL 中的 BETWEEN AND 将按照全庫路由處理。
• 複合分⽚政策 :對應 ComplexShardingStrategy。複合分⽚政策。提供對 SQL 語句中的 =, >, <, >=, <=, IN 和 BETWEEN AND 的分⽚操作⽀持。ComplexShardingStrategy ⽀持多分⽚鍵,由于多分⽚鍵之間的關系複雜,是以并未進⾏過多的封裝,而是直接将分⽚鍵值組合以及分⽚操作符透傳⾄分⽚算法,完全由應⽤開發者實作, 提供最⼤的靈活度。
• Hint 分⽚政策 :對應 HintShardingStrategy。通過 Hint 指定分⽚值而⾮從 SQL 中提取分⽚值的⽅式進⾏分⽚的政策。
• 不分⽚政策 :對應 NoneShardingStrategy。不分⽚的政策。
配置
分⽚規則 :分⽚規則配置的總⼊口。包含資料源配置、表配置、綁定表配置以及讀寫分離配置等。
資料源配置 :真實資料源清單。
表配置 : 邏輯表名稱、資料節點與分表規則的配置。 資料節點配置:⽤于配置邏輯表與真實表的映射關系。可分為均勻分布和⾃定義分布兩種形式。
指資料表在每個資料源内呈現均勻分布的态勢,例如: db0 ├── t_order0 └── t_order1 db1 ├── t_order0 └── t_order1 那麼資料節點的配置如下: db0.t_order0, db0.t_order1, db1.t_order0, db1.t_order1
- 均勻分布
- ⾃定義分布
指資料表呈現有特定規則的分布,例如: db0 ├── t_order0 └── t_order1 db1 └── t_order2 那麼資料節點的配置如下:db0.t_order0, db0.t_order1, db1.t_order2 分⽚政策配置: 對于分⽚政策存有資料源分⽚政策和表分⽚政策兩種次元。兩種政策的 API 完全相同。
⾃增主鍵⽣成政策:通過在客⼾端⽣成⾃增主鍵替換以資料庫原⽣⾃增主鍵的⽅式,做到分布式主鍵⽆重複
- 資料源分片政策:對應于 DatabaseShardingStrategy。⽤于配置資料被配置設定的⽬标資料源。
- 表分片政策:對應于 TableShardingStrategy。⽤于配置資料被配置設定的⽬标表,該⽬标表存在于該資料的⽬标資料源内。 故表分⽚政策是依賴于資料源分⽚政策的結果的。
行表達式
實作動機:
配置的簡化與⼀體化是⾏表達式所希望解決的兩個主要問題。 在繁瑣的資料分⽚規則配置中,随着資料節點的增多,⼤量的重複配置使得配置本⾝不易被維護。通過 ⾏表達式可以有效地簡化資料節點配置⼯作量。 對于常⻅的分⽚算法,使⽤ Java 代碼實作并不有助于配置的統⼀管理。通過⾏表達式書寫分⽚算法,可 以有效地将規則配置⼀同存放,更加易于浏覽與存儲。 文法說明 ⾏表達式的使⽤⾮常直覺,隻需要在配置中使⽤ ${ expression } 或 $->{ expression } 辨別⾏ 表達式即可。⽬前⽀持資料節點和分⽚算法這兩個部分的配置。⾏表達式的内容使⽤的是 Groovy 的文法, Groovy 能夠⽀持的所有操作,⾏表達式均能夠⽀持。例如: ${begin..end} 表⽰範圍區間 ${[unit1, unit2, unit_x]} 表⽰枚舉值 ⾏表達式中如果出現連續多個 ${ expression } 或 $->{ expression } 表達式,整個表達式最終 的結果将會根據每個⼦表達式的結果進⾏笛卡爾組合。例如,以下⾏表達式: ${['online','offline']}_table${1..3} 最終會解析為: online_table1,online_table2,online_table3,offline_table1,offline_table2,offline_table3 配置資料節點
對于均勻分布的資料節點,如果資料結構如下:
對于⾃定義的資料節點,如果資料結構如下:配置分⽚算法
對于隻有⼀個分⽚鍵的使⽤=和IN進⾏分⽚的SQL,可以使⽤⾏表達式代替編碼⽅式配置。
⾏表達式内部的表達式本質上是⼀段Groovy代碼,可以根據分⽚鍵進⾏計算的⽅式,傳回相應的真實資料源或真實表名稱。
例如:分為10個庫,尾數為0的路由到字尾為0的資料源,尾數為1的路由到字尾為1的資料源,以此類推。⽤于表⽰分⽚算法的⾏表達式為:
分布式主鍵
實作動機
傳統資料庫軟體開發中,主鍵⾃動⽣成技術是基本需求。而各個資料庫對于該需求也提供了相應的⽀持,
⽐如 MySQL 的⾃增鍵, Oracle 的⾃增序列等。資料分⽚後,不同資料節點⽣成全局唯⼀主鍵是⾮常棘⼿ 的問題。同⼀個邏輯表内的不同實際表之間的⾃增鍵由于⽆法互相感覺而産⽣重複主鍵。雖然可通過約 束⾃增主鍵初始值和步⻓的⽅式避免碰撞,但需引⼊額外的運維規則,使解決⽅案缺乏完整性和可擴充 性。 ⽬前有許多第三⽅解決⽅案可以完美解決這個問題,如 UUID 等依靠特定算法⾃⽣成不重複鍵,或者通過 引⼊主鍵⽣成服務等。為了⽅便⽤⼾使⽤、滿⾜不同⽤⼾不同使⽤場景的需求, Apache ShardingSphere 不僅提供了内置的分布式主鍵⽣成器,例如 UUID 、 SNOWFLAKE ,還抽離出分布式主鍵⽣成器的接口, ⽅便⽤⼾⾃⾏實作⾃定義的⾃增主鍵⽣成器。
内置的主鍵⽣成器
UUID 采⽤UUID.randomUUID()的⽅式産⽣分布式主鍵。 SNOWFLAKE 在分⽚規則配置子產品可配置每個表的主鍵⽣成政策,預設使⽤雪花算法(snowfake)⽣成64bit的⻓整型資料。
雪花算法是由Twitter公布的分布式主鍵⽣成算法,它能夠保證不同程序主鍵的不重複性,以及相同程序主鍵的有序性。
強制分片路由
實作動機
通過解析SQL語句提取分⽚鍵列與值并進⾏分⽚是ApacheShardingSphere對SQL零侵⼊的實作⽅式。若SQL語句中沒有分⽚條件,則⽆法進⾏分⽚,需要全路由。
在⼀些應⽤場景中,分⽚條件并不存在于SQL,而存在于外部業務邏輯。是以需要提供⼀種通過外部指定分⽚結果的⽅式,在ApacheShardingSphere中叫做Hint。
實作機制
ApacheShardingSphere使⽤ThreadLocal管理分⽚鍵值。可以通過程式設計的⽅式向HintManager中添加分⽚條件,該分⽚條件僅在目前線程内⽣效。
除了通過程式設計的⽅式使⽤強制分⽚路由,ApacheShardingSphere還計劃通過SQL中的特殊注釋的⽅式引⽤Hint,使開發者可以采⽤更加透明的⽅式使⽤該功能。
指定了強制分⽚路由的SQL将會⽆視原有的分⽚邏輯,直接路由⾄指定的真實資料節點。