1. 概述
老話說的好:選擇比努力更重要,如果選錯了道路,就很難成功。
言歸正傳,之前我們聊了使用 MyCat 實現Mysql的分庫分表和讀寫分離,MyCat是服務端的代理,使用MyCat的好處顯而易見,整個分庫分表和讀寫分離過程對Java程式來說是完全透明的,Java程式像連線Mysql一樣,去連線MyCat即可。
但MyCat的運維成本較高,需要有專門的運維人員去維護,所以今天我們來聊聊另一個實現Mysql分庫分表、讀寫分離的方案 —— ShardingSphere-JDBC。
ShardingSphere-JDBC 是一個輕量級的Java框架, 是客戶端代理,不需要MyCat的中間代理,使用Java程式可以通過配置直接去實現Mysql分庫分表和讀寫分離,適用於運維資源比較少的情況。
ShardingSphere-JDBC 支援同一庫內的分表,MyCat 是不支援的,MyCat 只能在不同庫內分表。
ShardingSphere-JDBC 不支援主庫雙寫或多寫,只支援一主多從的讀寫分離配置,因此 Mysql 叢集的高可用需要使用其他手段來實現,例如 MHA。
2. 場景介紹
分片1:
伺服器A IP:192.168.1.22 (Mysql從1)
伺服器B IP:192.168.1.12 (Mysql主1)
伺服器C IP:192.168.1.15 (Mysql主2)
伺服器D IP:192.168.1.16 (Mysql從2)
分片2:
伺服器E IP:192.168.1.11 (單點)
之前我們在前4臺伺服器上搭建了Mysql雙主雙從的高可用叢集,該叢集與伺服器E實現了分表分庫,本節我們使用ShardingSphere-JDBC去整合這個叢集。
關於Mysql雙主雙從叢集的具體搭建可參考以下文章:
《MyCat的快速搭建》(https://www.cnblogs.com/w84422/p/15394662.html)
《Mysql讀寫分離叢集的搭建且與MyCat進行整合》(https://www.cnblogs.com/w84422/p/15401259.html)
《Mysql雙主雙從高可用叢集的搭建且與MyCat進行整合》(https://www.cnblogs.com/w84422/p/15418403.html)
由於 ShardingSphere-JDBC 不支援主庫雙寫或多寫,因此我們把 伺服器C 也當做一個從庫來配置。
3. ShardingSphere-JDBC在Springboot中的具體使用
3.1 官網地址
https://shardingsphere.apache.org/index_zh.html
https://shardingsphere.apache.org/document/current/cn/overview/
3.2 引入依賴
這裡我們使用最新的 5.0.0-beta 版本
<dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId> <version>5.0.0-beta</version> </dependency>
3.3 配置JPA相關配置
# jpa 配置 spring.data.jpa.repositories.bootstrap-mode=default spring.data.jpa.repositories.enabled=true spring.jpa.database=mysql spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=update # 啟用懶載入 spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
這裡要特別注意,使用ShardingSphere-JDBC + JPA 一定要啟動懶載入配置,否則 getById 時會報錯。
3.4 配置資料來源
這裡我們按照場景介紹中描述的,配置5臺伺服器的資訊
# 配置真實資料來源 spring.shardingsphere.datasource.names=master0,master1,slave0,slave1,ds1 # 配置 伺服器A 資料來源 spring.shardingsphere.datasource.slave0.type=com.zaxxer.hikari.HikariDataSource spring.shardingsphere.datasource.slave0.driver-class-name=com.mysql.cj.jdbc.Driver spring.shardingsphere.datasource.slave0.jdbc-url=jdbc:mysql://192.168.1.22:3306/mycat spring.shardingsphere.datasource.slave0.username=zhuifengren spring.shardingsphere.datasource.slave0.password=Zhuifengren@123456 # 配置 伺服器B 資料來源 spring.shardingsphere.datasource.master0.type=com.zaxxer.hikari.HikariDataSource spring.shardingsphere.datasource.master0.driver-class-name=com.mysql.cj.jdbc.Driver spring.shardingsphere.datasource.master0.jdbc-url=jdbc:mysql://192.168.1.12:3306/mycat spring.shardingsphere.datasource.master0.username=zhuifengren spring.shardingsphere.datasource.master0.password=Zhuifengren@123456 # 配置 伺服器C 資料來源 spring.shardingsphere.datasource.master1.type=com.zaxxer.hikari.HikariDataSource spring.shardingsphere.datasource.master1.driver-class-name=com.mysql.cj.jdbc.Driver spring.shardingsphere.datasource.master1.jdbc-url=jdbc:mysql://192.168.1.15:3306/mycat spring.shardingsphere.datasource.master1.username=zhuifengren spring.shardingsphere.datasource.master1.password=Zhuifengren@123456 # 配置 伺服器D 資料來源 spring.shardingsphere.datasource.slave1.type=com.zaxxer.hikari.HikariDataSource spring.shardingsphere.datasource.slave1.driver-class-name=com.mysql.cj.jdbc.Driver spring.shardingsphere.datasource.slave1.jdbc-url=jdbc:mysql://192.168.1.16:3306/mycat spring.shardingsphere.datasource.slave1.username=zhuifengren spring.shardingsphere.datasource.slave1.password=Zhuifengren@123456 # 配置 伺服器E 資料來源 spring.shardingsphere.datasource.ds1.type=com.zaxxer.hikari.HikariDataSource spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.cj.jdbc.Driver spring.shardingsphere.datasource.ds1.jdbc-url=jdbc:mysql://192.168.1.11:3306/mycat spring.shardingsphere.datasource.ds1.username=zhuifengren spring.shardingsphere.datasource.ds1.password=Zhuifengren@123456
3.5 配置 分片1 的讀寫分離策略
這裡我們使用輪詢演算法,具體的演算法可參見 ShardingSphere 官網。
裡面的 database-balance 是自定義的名稱,與下面的負載均衡演算法配置保持一致即可。
特別注意一點,ShardingSphere裡面的自定義名稱,一定不要包含下劃線,否則會報錯,雖然官網給出的示例就是包含下劃線的。
# 讀寫分離配置 # 寫資料來源名稱 spring.shardingsphere.rules.readwrite-splitting.data-sources.ds0.write-data-source-name=master0 # 讀資料來源名稱,多個從資料來源用逗號分隔 spring.shardingsphere.rules.readwrite-splitting.data-sources.ds0.read-data-source-names=master1,slave0,slave1 # 負載均衡演算法名稱 spring.shardingsphere.rules.readwrite-splitting.data-sources.ds0.load-balancer-name=database-balance # 是否啟用查詢一致性路由 spring.shardingsphere.rules.readwrite-splitting.data-sources.ds0.query-consistent=false # 負載均衡演算法配置 # 負載均衡演算法型別,這裡配置為輪詢 spring.shardingsphere.rules.readwrite-splitting.load-balancers.database-balance.type=ROUND_ROBIN
3.6 配置 user 表的分庫分表規則
之前MyCat中我們使用的是 MyCat 預設的 auto-sharding-long 演算法,user 表的 id 為 0 到 5000000 時儲存在第一個分片,大於5000000儲存在第二個分片,這裡我們還使用這個演算法。
當然也可以使用其他演算法,例如 取模,大家可參見ShardingSphere的官網文件自行配置。
# 配置 user 表規則 spring.shardingsphere.rules.sharding.tables.user.actual-data-nodes=ds$->{[0,1]}.user # 配置分庫策略 spring.shardingsphere.rules.sharding.tables.user.database-strategy.standard.sharding-column=id spring.shardingsphere.rules.sharding.tables.user.database-strategy.standard.sharding-algorithm-name=database-inline # 配置分表策略 spring.shardingsphere.rules.sharding.tables.user.table-strategy.standard.sharding-column=id spring.shardingsphere.rules.sharding.tables.user.table-strategy.standard.sharding-algorithm-name=table-inline spring.shardingsphere.rules.sharding.sharding-algorithms.database-inline.type=INLINE spring.shardingsphere.rules.sharding.sharding-algorithms.database-inline.props.algorithm-expression=ds$->{(id <= 5000000)?0:1} spring.shardingsphere.rules.sharding.sharding-algorithms.table-inline.type=INLINE spring.shardingsphere.rules.sharding.sharding-algorithms.table-inline.props.algorithm-expression=user
3.7 JPA相關程式碼
User實體類:
@Entity @Table(name="user") @Setter @Getter @Builder @AllArgsConstructor @NoArgsConstructor public class User { @Id private Integer id; private String name; @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + '}'; } }
User資料訪問類:
public interface UserRepository extends JpaRepository<User, Integer> { }
3.8 驗證
這裡使用JPA操作增、刪、改、查操作是沒有任何問題的,資料落庫的分片也正確。
3.9 不得不說的幾個坑
1)配置ShardingSphere-JDBC時,自定義的名稱不要包含下劃線,包含了會報錯, 本人當時是跟了半天的原始碼才解決。
正確的命名:database-inline、table-inline、database-balance
錯誤的命名:database_inline、table_inline、database_balance
2)使用JPA需要開啟懶載入,否則會報錯。
3)不支援主庫雙寫或多寫,需要用其他手段保證叢集的高可用。
4)官網文件寫的不是很詳細,很多細節需要自己摸索,例如 分片表示式 和 分片策略 的配置都沒有給出示例。相對來說MyCat的官網文件就詳細很多。
4. 綜述
今天聊了一下 使用ShardingSphere-JDBC完成Mysql的分庫分表和讀寫分離,希望可以對大家的工作有所幫助。
大家可以根據自己的喜好去選擇使用 MyCat 或是 ShardingSphere-JDBC。
歡迎幫忙點贊、評論、轉發、加關注 :)
關注追風人聊Java,每天更新Java乾貨。
5. 個人公眾號
追風人聊Java,歡迎大家關注