Sharding-JDBC 使用入门和基本配置
服務器
【技術沙龍002期】數據中臺:宜信敏捷數據中臺建設實踐|宜信技術沙龍 將于5月23日晚8點線上直播,點擊報名
一、什么是Sharding-JDBC
Sharding-JDBC定位為輕量級Java框架,在Java的JDBC層提供的額外服務。它使用客戶端直連數據庫,以jar包形式提供服務,無需額外部署和依賴,可理解為增強版的JDBC驅動,完全兼容JDBC和各種ORM框架。
二、Sharding-JDBC能做什么
分庫 & 分表
讀寫分離
分布式主鍵
分布式事務
三、適用項目框架
Sharding-JDBC適用于:
任何基于Java的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。
基于任何第三方的數據庫連接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP等。
支持任意實現JDBC規范的數據庫,目前支持mysql,Oracle,SQLServer和PostgreSQL。
四、Maven依賴
<!--shardingjdbc開始-->
<dependency>
<groupId>io.shardingsphere</groupId>
<artifactId>sharding-core</artifactId>
<version>${sharding.version}</version>
</dependency>
<dependency>
<groupId>io.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-namespace</artifactId>
<version>${sharding.version}</version>
</dependency>
<!—如果不配置分布式事務的話配置上邊兩個就夠了-->
<!--分布式事務引用依賴-->
<dependency>
<groupId>io.shardingsphere</groupId>
<artifactId>sharding-transaction-2pc-xa</artifactId>
<version>${sharding.version}</version>
</dependency>
<dependency>
<groupId>io.shardingsphere</groupId>
<artifactId>sharding-transaction-spring</artifactId>
<version>${sharding.version}</version>
</dependency>
<!--shardingjdbc結束-->
<!--AspectJAOP支持-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectjweaver.version}</version>
</dependency>
五、讀寫分離
5.1 數據源配置
先配置數據源
也可以配置讀寫分離
以下配置是
ds0
和
ds1
兩個數據庫的主和從一共四個數據源。
parentDs
是數據源公共的配置,抽出去以免寫重復代碼。
<!--ds0的主-->
<beanid="ds0_master"class="com.alibaba.druid.pool.DruidDataSource"destroy-method="close"parent="parentDs">
<propertyname="driverClassName"value=""/>
<propertyname="url"value=""/>
</bean>
<!--ds0的從-->
<beanid="ds0_slave"class="com.alibaba.druid.pool.DruidDataSource"destroy-method="close"parent="parentDs">
<propertyname="driverClassName"value=""/>
<propertyname="url"value="${sharding.connection.url.0}"/>
</bean>
<!--ds1的主-->
<beanid="ds1_master"class="com.alibaba.druid.pool.DruidDataSource"destroy-method="close"parent="parentDs">
<propertyname="driverClassName"value=""/>
<propertyname="url"value="${sharding.connection.url.1}"/>
</bean>
<!--ds1的從-->
<beanid="ds1_slave"class="com.alibaba.druid.pool.DruidDataSource"destroy-method="close"parent="parentDs">
<propertyname="driverClassName"value=""/>
<propertyname="url"value="${sharding.connection.url.1}"/>
</bean>
5.2 讀寫分離配置
只配置主從不配置分庫分表的情況如下,如果要配置分庫分表則不需要下面這個配置。
master-data-source-name
是主數據源ID
slave-data-source-names
是從數據源ID
<master-slave:data-sourceid="masterSlaveDataSource"master-data-source-name="ds0_master,ds1_master"slave-data-source-names="ds0_slave,ds1_slave">
<master-slave:props>
<propkey="sql.show">${sql_show}</prop>
<propkey="executor.size">10</prop>
<propkey="foo">bar</prop>
</master-slave:props>
</master-slave:data-source>
5.3 讀寫分離和分庫分表一起配置
如果讀寫分離和分庫分表一起使用的話把主從路由配置到 shardingdata-source下就可以了。
sharding:master-slave-rule
的 id 就是配置出來的邏輯的數據源的名稱,如果多個從的話還可以通過配置strategy-ref來配置負載均衡。
master-data-source
配置的是主庫數據源ID 。
slave-data-source
配置的是從庫數據源ID,多個以逗號分開。
<!--sharding數據源--> <sharding:data-sourceid="shardingDataSource"> <!--讀寫分離的話要把所有的主從數據源都寫在這里--> <sharding:sharding-rule data-source-names="ds0_master,ds0_slave,ds1_master,ds1_slave"> <!--讀寫分離的路由一主一從配置strategy-ref--> <sharding:master-slave-rules> <sharding:master-slave-ruleid="ds0"master-data-source-name="ds0_master"slave-data-source-names="ds0_slave"/> <sharding:master-slave-ruleid="ds1"master-data-source-name="ds1_master"slave-data-source-names="ds1_slave"/> </sharding:master-slave-rules> <!--讀寫分離配置結束--> <sharding:table-rules> <!—這里是分庫分表路由的配置--> </sharding:table-rules> <sharding:binding-table-rules> <!—-綁定表的配置--> </sharding:binding-table-rules> </sharding:sharding-rule> <sharding:props> <!--顯示SQL--> <propkey="sql.show">true</prop> </sharding:props> </sharding:data-source>
六、數據分片
6.1 分片支持
Sharding-JDBC提供了5種分片策略。由于分片算法和業務實現緊密相關,因此Sharding-JDBC并未提供內置分片算法,而是通過分片策略將各種場景提煉出來,提供更高層級的抽象,并提供接口讓應用開發者自行實現分片算法。
StandardShardingStrategy
標準分片策略。提供對SQL語句中的=, IN和BETWEEN AND的分片操作支持。StandardShardingStrategy只支持單分片鍵,提供PreciseShardingAlgorithm和RangeShardingAlgorithm兩個分片算法。PreciseShardingAlgorithm是必選的,用于處理=和IN的分片;RangeShardingAlgorithm是可選的,用于處理BETWEEN AND分片,如果不配置RangeShardingAlgorithm,SQL中的BETWEEN AND將按照全庫路由處理。
ComplexShardingStrategy
復合分片策略。提供對SQL語句中的=, IN和BETWEEN AND的分片操作支持。ComplexShardingStrategy支持多分片鍵,由于多分片鍵之間的關系復雜,因此Sharding-JDBC并未做過多的封裝,而是直接將分片鍵值組合以及分片操作符交于算法接口,完全由應用開發者實現,提供最大的靈活度。
InlineShardingStrategy
Inline表達式分片策略。使用Groovy的Inline表達式,提供對SQL語句中的=和IN的分片操作支持。InlineShardingStrategy只支持單分片鍵,對于簡單的分片算法,可以通過簡單的配置使用,從而避免繁瑣的Java代碼開發,如: tuser${user_id % 8} 表示t_user表按照user_id按8取模分成8個表,表名稱為t_user_0到t_user_7。
HintShardingStrategy
通過Hint而非SQL解析的方式分片的策略。
NoneShardingStrategy
不分片的策略。
6.2 分片配置
標準分片配置
<!--標準分片策略。--> <beanid="demoUserStandardStrategy"class="shard.strategy.DemoUserStandardStrategy"/> <sharding:standard-strategyid="shardingDemoUserStandardStrategy" precise-algorithm-ref="demoUserStandardStrategy"sharding-column="id"range-algorithm-ref=""/>
DemoUserStandardStrategy標準分片要實現 PreciseShardingAlgorithm 接口,doSharding的兩個參數一個是所有數據源的cllection.另一個參數是執行SQL時傳過來的分片的值。
/**
*根據ID取
*標準分片策略
*用于處理=和IN的分片
*@authoryulonggao
*@date2019/1/3114:35
*/
@Slf4j
publicclassDemoUserStandardStrategyimplementsPreciseShardingAlgorithm<Long>{
@Override
publicStringdoSharding(Collection<String>collection,PreciseShardingValue<Long>preciseShardingValue){
//這個里邊有異常會被處理掉,然后導致拿不到分片。但出異常一般是業務代碼寫錯了。
//每條指定分片的操作都會調用此方法,如果是in條件查詢的話每個值會調用一次此方法,如果是批量插入也是每一條都要調用一次進行分片
log.info("DemoUserStandardStrategy_preciseShardingValue={}",preciseShardingValue);
Longsuffix=preciseShardingValue.getValue()%4;
log.info("suffix={}",suffix);
finalStringtargetDb=String.valueOf(Math.abs(suffix.intValue()));
StringshardingValue=collection.stream().filter(p->p.endsWith(targetDb)).findFirst().get();
log.info("preciseShardingValue={},shardingValue={}",preciseShardingValue,shardingValue);
returnshardingValue;
}
強制分片
<!--強制路由分片策略-->
<beanid="demoUserHintStrategy"class="shard.strategy.DemoUserHintStrategy"/>
<!--強制路由例子使用-->
<sharding:hint-strategyid="shardingDemoUserHintStrategy"algorithm-ref="demoUserHintStrategy"/>
DemoUserHintStrategy的Java如下,強制分片要實現HintShardingAlgorithm接口。
/**
*DemoUserHint強制路由分片策略,其實可以共用,只是例子
*@authoryulonggao
*@date2019/1/3114:35
*/
@Slf4j
publicclassDemoUserHintStrategyimplementsHintShardingAlgorithm{
@Override
publicCollection<String>doSharding(Collection<String>availableTargetNames,ShardingValueshardingValue){
//availableTargetNames這個參數是所有的dataSource的集合,shardingValue是HintManager傳過來的分片信息
log.info("DemoUserHintStrategy_availableTargetNames={}",availableTargetNames);
log.info("DemoUserHintStrategy_shardingValue={}",shardingValue);
ListShardingValuelistShardingValue=(ListShardingValue)shardingValue;
CollectionshardingValueList=listShardingValue.getValues();
//因為調用的時候分片是直接傳的DataSource的名稱,所以直接返回就可以了,如果傳其它值則要加業務邏輯進行分片篩選
//返回結果只能是availableTargetNames里邊所包含的
returnshardingValueList;
}
}
生成分部式ID的配置,生成主鍵的類要實現KeyGenerator接口。
<!—主鍵生成--> <beanid="keyId"class="shard.key.DefaultKeyGenerator"/>
七、分布式事務
把下面這行代碼配置在spring里,shardingTransaction.xml 是jar包里邊帶的。
文件的源碼只有兩行配置:
<beanid="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <propertyname="dataSource"ref="shardingDataSource"></property> </bean> <tx:annotation-driventransaction-manager="transactionManager"/> <!--事務支持--> <importresource="classpath:META-INF/shardingTransaction.xml"/>
使用注解配置事務要同時使用ShardingTransactionType和Transactional兩個注解。
/**
*注意:@ShardingTransactionType需要同Spring的@Transactional配套使用,事務才會生效。
*@paramparam
*@return
*/
@ShardingTransactionType(TransactionType.XA)
@Transactional(rollbackFor=Exception.class)
@Override
publicintaddParam(DemoParamparam){
log.info("addParam-param={}",param);
returndemoParamDao.addParam(param);
}
7.1 支持程度
完全支持非跨庫事務,例如:僅分表或分庫但是路由的結果在單庫中。
完全支持因邏輯異常導致的跨庫事務。例如:同一事務中跨兩個庫更新,更新完畢后,拋出空指針,則兩個庫的內容都能回滾。
支持數據庫字段約束造成的回滾。
不支持因網絡、硬件異常導致的跨庫事務。例如:同一事務中跨兩個庫更新,更新完畢后、未提交之前,第一個庫死機,則只有第二個庫數據提交。
八、其他問題
關于order by 排序,如果排序的字段不在查詢結果中,生成的SQL也會被帶上,但結果不返回給你。
九、參考文檔
https://shardingsphere.apache.org/document/current/cn/manual/sharding-jdbc/usage/sharding/
作者:高玉瓏
來源:
宜信技術學院
總結
以上是生活随笔為你收集整理的Sharding-JDBC 使用入门和基本配置的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SLAM: 图像角点检测的Fast算法(
- 下一篇: 杭州·云栖大会宣布多款核心云产品降价,最