ShardingSphere入門實戰(1)-Sharding-JDBC使用
阿新 • • 發佈:2020-07-30
ShardingSphere是一套開源的分散式資料庫中介軟體解決方案組成的生態圈,它由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar(計劃中)這3款相互獨立的產品組成。 他們均提供標準化的資料分片、分散式事務和資料庫治理功能,可適用於如Java同構、異構語言、雲原生等各種多樣化的應用場景。具體介紹可以檢視官網https://shardingsphere.apache.org/。本文主要介紹在Spring Boot工程中使用Sharding-JDBC,文中使用到的軟體版本:Java 1.8.0_191、sharding-jdbc-core 4.1.1、MySQL 5.7。
1、引入依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-test</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> </dependency> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-boot-starter</artifactId> <version>4.1.1</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.21</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.20</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13</version> </dependency>
2、資料分片
2.1、對應配置
spring:
shardingsphere:
datasource:
names: ds0,ds1 #資料來源名稱,多資料來源以逗號分隔
ds0:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://10.40.94.232:3306/qm?useUnicode=true;characterEncoding=UTF-8
username: root
password: ooxx5201314
ds1:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://10.198.0.10:3306/itest?useUnicode=true;characterEncoding=UTF-8
username: root
password: Root_123!
sharding:
tables:
t_user: #邏輯表名,在一個庫裡分表:ds0.t_user_0,ds0.t_user_1
actual-data-nodes: ds0.t_user_$->{0..1}
table-strategy: #表分片策略
inline: #行表示式分片策略
sharding-column: user_id #分片的欄位
algorithm-expression: t_user_$->{user_id % 2} #分片的演算法
t_dept: #分庫,兩個庫裡建系統的表:ds0.t_dept,ds1.t_dept
actual-data-nodes: ds$->{0..1}.t_dept
database-strategy: #資料庫分片策略
inline: #行表示式分片策略
sharding-column: dept_id #分片的欄位
algorithm-expression: ds$->{dept_id % 2} #分片的演算法
props:
sql:
show: true
2.2、對應程式
/** * 資料分片 * t_user在同一個庫裡分表(t_user_0,t_user_1) * t_dept分庫 */ @Test public void fragmentation() { Connection con = null; try { con = dataSource.getConnection(); con.setAutoCommit(false); Statement st = con.createStatement(); //插入ds0.t_user_0表 st.executeUpdate("insert into t_user(user_id,user_name,age) values(10,'趙雲', 30)"); //插入ds0.t_user_1表 st.executeUpdate("insert into t_user(user_id,user_name,age) values(11,'張飛', 31)"); //插入ds0.t_dept表 st.executeUpdate("insert into t_dept(dept_id,dept_name) values(10,'dept10')"); //插入ds1.t_dept表 st.executeUpdate("insert into t_dept(dept_id,dept_name) values(11,'dept11')"); ResultSet rs = st.executeQuery("select user_id,user_name from t_user where user_id in(10,11)"); while (rs.next()) { logger.info("user_id={},user_name={}", rs.getString("user_id"), rs.getString("user_name")); } rs = st.executeQuery("select dept_id,dept_name from t_dept where dept_id in(10,11)"); while (rs.next()) { logger.info("dept_id={},dept_name={}", rs.getString("dept_id"), rs.getString("dept_name")); } con.commit(); } catch (Exception e) { JdbcUtil.rollback(con); e.printStackTrace(); } finally { JdbcUtil.close(con); } }
3、讀寫分離
3.1、對應配置
spring:
shardingsphere:
datasource:
names: master,slave0
master:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://10.40.94.232:3306/qm?useUnicode=true;characterEncoding=UTF-8
username: root
password: ooxx5201314
slave0:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://10.198.0.10:3306/itest?useUnicode=true;characterEncoding=UTF-8
username: root
password: Root_123!
masterslave:
name: ms
master-data-source-name: master
slave-data-source-names: slave0
props:
sql:
show: true
3.2、對應程式
/** * 讀寫分離,主庫寫,從庫讀 * 同一執行緒且同一資料庫連線內,如有寫入操作,以後的讀操作均從主庫讀取,用於保證資料一致性 */ @Test public void readWrite() { Connection con = null; try { con = dataSource.getConnection(); Statement st = con.createStatement(); //從slave0讀資料 ResultSet rs = st.executeQuery("select * from wlw_all where id<900"); while (rs.next()) { System.out.println(rs.getString("id") + "|" + rs.getString("zonename")); } //寫入master st.executeUpdate("insert into tree_test(id,name) values(11,'測試')"); //從master讀資料 rs = st.executeQuery("select * from a_orm"); while (rs.next()) { System.out.println(rs.getString(1) + "|" + rs.getString(2)); } } catch (Exception e) { e.printStackTrace(); } finally { JdbcUtil.close(con); } } /** * 讀寫分離,強制主庫路由 */ @Test public void hintMasterRouteOnly() { Connection con = null; try { con = dataSource.getConnection(); Statement st = con.createStatement(); HintManager hintManager = HintManager.getInstance(); //主庫路由 hintManager.setMasterRouteOnly(); //從master讀資料 ResultSet rs = st.executeQuery("select * from a_orm"); while (rs.next()) { logger.info(rs.getString(1) + "|" + rs.getString(2)); } hintManager.close(); } catch (Exception e) { e.printStackTrace(); } finally { JdbcUtil.close(con); } }
4、完整程式碼
package com.inspur.demo.shardingsphere; import com.inspur.demo.shardingsphere.util.JdbcUtil; import org.apache.shardingsphere.api.hint.HintManager; import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import javax.annotation.Resource; import javax.sql.DataSource; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; /** * ShardingJdbc使用樣例 */ @RunWith(SpringRunner.class) @SpringBootTest public class ShardingJdbcCase { private static Logger logger = LoggerFactory.getLogger(ShardingJdbcCase.class); @Resource private DataSource dataSource; /** * 資料分片 * t_user在同一個庫裡分表(t_user_0,t_user_1) * t_dept分庫 */ @Test public void fragmentation() { Connection con = null; try { con = dataSource.getConnection(); con.setAutoCommit(false); Statement st = con.createStatement(); //插入ds0.t_user_0表 st.executeUpdate("insert into t_user(user_id,user_name,age) values(10,'趙雲', 30)"); //插入ds0.t_user_1表 st.executeUpdate("insert into t_user(user_id,user_name,age) values(11,'張飛', 31)"); //插入ds0.t_dept表 st.executeUpdate("insert into t_dept(dept_id,dept_name) values(10,'dept10')"); //插入ds1.t_dept表 st.executeUpdate("insert into t_dept(dept_id,dept_name) values(11,'dept11')"); ResultSet rs = st.executeQuery("select user_id,user_name from t_user where user_id in(10,11)"); while (rs.next()) { logger.info("user_id={},user_name={}", rs.getString("user_id"), rs.getString("user_name")); } rs = st.executeQuery("select dept_id,dept_name from t_dept where dept_id in(10,11)"); while (rs.next()) { logger.info("dept_id={},dept_name={}", rs.getString("dept_id"), rs.getString("dept_name")); } con.commit(); } catch (Exception e) { JdbcUtil.rollback(con); e.printStackTrace(); } finally { JdbcUtil.close(con); } } /** * 讀寫分離,主庫寫,從庫讀 * 同一執行緒且同一資料庫連線內,如有寫入操作,以後的讀操作均從主庫讀取,用於保證資料一致性 */ @Test public void readWrite() { Connection con = null; try { con = dataSource.getConnection(); Statement st = con.createStatement(); //從slave0讀資料 ResultSet rs = st.executeQuery("select * from wlw_all where id<900"); while (rs.next()) { System.out.println(rs.getString("id") + "|" + rs.getString("zonename")); } //寫入master st.executeUpdate("insert into tree_test(id,name) values(11,'測試')"); //從master讀資料 rs = st.executeQuery("select * from a_orm"); while (rs.next()) { System.out.println(rs.getString(1) + "|" + rs.getString(2)); } } catch (Exception e) { e.printStackTrace(); } finally { JdbcUtil.close(con); } } /** * 讀寫分離,強制主庫路由 */ @Test public void hintMasterRouteOnly() { Connection con = null; try { con = dataSource.getConnection(); Statement st = con.createStatement(); HintManager hintManager = HintManager.getInstance(); //主庫路由 hintManager.setMasterRouteOnly(); //從master讀資料 ResultSet rs = st.executeQuery("select * from a_orm"); while (rs.next()) { logger.info(rs.getString(1) + "|" + rs.getString(2)); } hintManager.close(); } catch (Exception e) { e.printStackTrace(); } finally { JdbcUtil.close(con); } } }ShardingJdbcCase