分庫分表實踐-Sharding-JDBC

關於為什麼要做分庫分表,什麼是水平分表,垂直分表等概念,相信大家都知道,這裡就不在贅述了。

本文只講述使用Sharding-JDBC做分庫分表的一些實踐經驗,如果有錯誤歡迎大家指出。

什麼是Sharding-JDBC

分庫分表實踐-Sharding-JDBC

Sharding-jdbc是噹噹網開源的一款 客戶端代理 中間件。Sharding-jdbc包含分庫分片和讀寫分離功能。對應用的代碼沒有侵入型,幾乎沒有任何改動,兼容主流orm框架,主流數據庫連接池。目前屬於Apache的孵化項目ShardingSphere。

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

適用於任何基於JDBC的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。

支持任何第三方的數據庫連接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP等。

支持任意實現JDBC規範的數據庫。目前支持MySQL,Oracle,SQLServer,PostgreSQL以及任何遵循SQL92標準的數據庫。

官方文檔地址

ShardingSphere: https://shardingsphere.apache.org/

GitHub的地址: https://github.com/apache/incubator-shardingsphere

一些建議和說明

不過我這裡建議大家可以簡單過下官方文檔,因為文檔並不全面或者說感覺並不是最新的。

建議大家重點可以放在git上官方的examples

目前官方最新的版本是4.0,如果使用springboot創建,可以使用下面的依賴即可。

<code><dependency>
<groupid>org.apache.shardingsphere/<groupid>
<artifactid>sharding-jdbc-spring-boot-starter/<artifactid>
<version>4.0.0/<version>
/<dependency>/<code>

Sharding-jdbc功能強大,但是本文重點在於下面幾點,未涉及的地方可以翻閱文檔查看。

1、單庫分表

2、分庫分表(含分庫單表)

3、分表後的查詢

4、分表事務處理

無論上述哪種分庫亦或是分表類型,核心無非是下面幾個配置:

1、配置數據源,明確你有多少個數據源

2、定義表名,分表的邏輯表名(t_order)和所有物理表名(t_order_0,t_order_1)

3、定義分庫列以及分庫算法

4、定義分表列以及分表算法

代碼實現

單庫分表

sharding-jdbc優勢就是對代碼沒有侵入性,基本上不用動我們原來的代碼,只是將相關數據庫連接的配置更換為sharding的配置即可。

以我的個人實踐項目為例:

原來不分表時的配置:

<code>#項目配置
spring:
#數據連接配置
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://xxx.xx.xx.xx:3306/yyms?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: xxx
password: xxx/<code>

使用sharding後的配置

<code># 分表配置
spring:
shardingsphere:
datasource:
names: yyms
yyms:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://xxx.xx.xx.xx:3306/yyms?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: xx
password: xxx
sharding:
tables:
# 表名
sys_log:
actual-data-nodes: yyms.sys_log_$->{0..1}
# 分表配置,根據id分表
table-strategy:

inline:
sharding-column: id
algorithm-expression: sys_log_$->{id % 2}
# 配置字段的生成策略,column為字段名,type為生成策略,sharding默認提供SNOWFLAKE和UUID兩種,可以自己實現其他策略
key-generator:
column: id
type: SNOWFLAKE
props:
sql:
show: true/<code>

上面的配置基本上就實現了單庫對sys_log表的拆分,根據id取模算法,拆分為sys_log_0和sys_log_1兩張表。代碼層面沒有任何改動就實現了拆分,拆分後效果圖如下。

分庫分表實踐-Sharding-JDBC

注意哦,sys_log表拆分後是實際不存在的。

當然了,使用官方的默認配置很多時候並不能滿足我們的需求。

假如拿到一條數據的id後再去計算數據在哪個庫,無疑對我們日常的運維維護工作造成極大的不便。這裡我們可以通過一些簡單的自定義開發配置實現。

比如我想要id最後一位展示數據所處表所在序號。

多庫分表

先展示個多庫單表的案例

<code>spring:
shardingsphere:
datasource:
names: ds0,ds1
ds_1:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://xxxxxx:3306/ds1?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: xxxx
password: xxx
ds0:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://xxxxx:3306/ds0?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: xxxx
password: xxxx
sharding:
default-data-source-name: ds0
default-database-strategy:
inline:
sharding-column: id
algorithm-expression: ds$->{id % 2}

tables:
sys_log:
actual-data-nodes: ds$->{0..1}.sys_log
key-generator:
column: id
type: SNOWFLAKE
props:
worker:
id: 123/<code>

把單張表拆分到多個庫,同樣使用sys_log。效果圖如下:

分庫分表實踐-Sharding-JDBC

其實分庫分表無非就是上面兩種模式的集合,具體配置的選項,可以參考官方案例配置》》》 我是鏈接

分庫分表後的查詢

select * from sys_log where id='444271380247588864'

接著上面的案例,以上面的語句為例,id為分庫列,sharding經過解析後定位到對應的數據源,直接執行下面的查詢。

select * from sys_log where id='444271380247588864'

假如我們的查詢調節不包含分庫列,以下面的語句為例:

select * from sys_log where user_name='zhangsan

執行後出現兩條sql語句。我們在兩個庫均為5條數據,查詢後的結果集為10條數據,符合我們的預期。

數據庫:

分庫分表實踐-Sharding-JDBC

結果集:

分庫分表實踐-Sharding-JDBC

結論:當搜索條件含有分庫列(分表列),這時候sharing會首先調用分庫分表策略類,直接找到對應的數據庫和對應子表。而當搜索條件不含有分庫列時,這時候引擎就不會再調用策略類了,而是會直接認定目標庫為全部庫或表,上述案例中目標庫就是,[ds0,ds1]兩個數據源,既然目標庫有兩個,後面生成的DataNode,TableUnits,PreparedStatementUnit 將是以前數量的兩倍,所以這回,引擎最終將會發起多個sql語句的併發執行,併合並最終的結果再返回。

分庫分表後的事務

Sharding-Sphere同時支持XA和柔性事務,它允許每次對數據庫的訪問,可以自由選擇事務類型。分佈式事務對業務操作完全透明,極大地降低了引入分佈式事務的成本。

分佈式事務我感覺在官方的文檔和案例中寫的已經是比較完善的了,這裡大家可以參考: 我是鏈接 官方案例實現,這裡就不在贅述了。


分享到:


相關文章: