spring boot使用sharding jdbc的配置方式
本文介紹了spring boot使用sharding jdbc的配置方式,分享給大家,具體如下:
說(shuō)明
要排除DataSourceAutoConfiguration,否則多數(shù)據(jù)源無(wú)法配置
@SpringBootApplication @EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
配置的多個(gè)數(shù)據(jù)源交給sharding-jdbc管理,sharding-jdbc創(chuàng)建一個(gè)DataSource數(shù)據(jù)源提供給mybatis使用
官方文檔:http://shardingjdbc.io/index_zh.html
步驟
配置多個(gè)數(shù)據(jù)源,數(shù)據(jù)源的名稱最好要有一定的規(guī)則,方便配置分庫(kù)的計(jì)算規(guī)則
@Bean(initMethod="init", destroyMethod="close", name="dataSource0") @ConfigurationProperties(prefix = "spring.datasource") public DataSource dataSource0(){ return new DruidDataSource(); } @Bean(initMethod="init", destroyMethod="close", name="dataSource1") @ConfigurationProperties(prefix = "spring.datasource2") public DataSource dataSource1(){ return new DruidDataSource(); }
配置數(shù)據(jù)源規(guī)則,即將多個(gè)數(shù)據(jù)源交給sharding-jdbc管理,并且可以設(shè)置默認(rèn)的數(shù)據(jù)源,當(dāng)表沒有配置分庫(kù)規(guī)則時(shí)會(huì)使用默認(rèn)的數(shù)據(jù)源
@Bean public DataSourceRule dataSourceRule(@Qualifier("dataSource0") DataSource dataSource0, @Qualifier("dataSource1") DataSource dataSource1){ Map<String, DataSource> dataSourceMap = new HashMap<>(); dataSourceMap.put("dataSource0", dataSource0); dataSourceMap.put("dataSource1", dataSource1); return new DataSourceRule(dataSourceMap, "dataSource0"); }
配置數(shù)據(jù)源策略和表策略,具體策略需要自己實(shí)現(xiàn)
@Bean public ShardingRule shardingRule(DataSourceRule dataSourceRule){ //表策略 TableRule orderTableRule = TableRule.builder("t_order") .actualTables(Arrays.asList("t_order_0", "t_order_1")) .tableShardingStrategy(new TableShardingStrategy("order_id", new ModuloTableShardingAlgorithm())) .dataSourceRule(dataSourceRule) .build(); TableRule orderItemTableRule = TableRule.builder("t_order_item") .actualTables(Arrays.asList("t_order_item_0", "t_order_item_1")) .tableShardingStrategy(new TableShardingStrategy("order_id", new ModuloTableShardingAlgorithm())) .dataSourceRule(dataSourceRule) .build(); //綁定表策略,在查詢時(shí)會(huì)使用主表策略計(jì)算路由的數(shù)據(jù)源,因此需要約定綁定表策略的表的規(guī)則需要一致,可以一定程度提高效率 List<BindingTableRule> bindingTableRules = new ArrayList<BindingTableRule>(); bindingTableRules.add(new BindingTableRule(Arrays.asList(orderTableRule, orderItemTableRule))); return ShardingRule.builder() .dataSourceRule(dataSourceRule) .tableRules(Arrays.asList(orderTableRule, orderItemTableRule)) .bindingTableRules(bindingTableRules) .databaseShardingStrategy(new DatabaseShardingStrategy("user_id", new ModuloDatabaseShardingAlgorithm())) .tableShardingStrategy(new TableShardingStrategy("order_id", new ModuloTableShardingAlgorithm())) .build(); }
創(chuàng)建sharding-jdbc的數(shù)據(jù)源DataSource,MybatisAutoConfiguration會(huì)使用此數(shù)據(jù)源
@Bean("dataSource") public DataSource shardingDataSource(ShardingRule shardingRule){ return ShardingDataSourceFactory.createDataSource(shardingRule); }
需要手動(dòng)配置事務(wù)管理器(原因未知)
//需要手動(dòng)聲明配置事務(wù) @Bean public DataSourceTransactionManager transactitonManager(@Qualifier("dataSource") DataSource dataSource){ return new DataSourceTransactionManager(dataSource); }
分庫(kù)策略的簡(jiǎn)單實(shí)現(xiàn),接口:DatabaseShardingAlgorithm
import java.util.Collection; import java.util.LinkedHashSet; import com.dangdang.ddframe.rdb.sharding.api.ShardingValue; import com.dangdang.ddframe.rdb.sharding.api.strategy.database.SingleKeyDatabaseShardingAlgorithm; import com.google.common.collect.Range; /** * Created by fuwei.deng on 2017年5月11日. */ public class ModuloDatabaseShardingAlgorithm implements SingleKeyDatabaseShardingAlgorithm<Long> { @Override public String doEqualSharding(Collection<String> databaseNames, ShardingValue<Long> shardingValue) { for (String each : databaseNames) { if (each.endsWith(shardingValue.getValue() % 2 + "")) { return each; } } throw new IllegalArgumentException(); } @Override public Collection<String> doInSharding(Collection<String> databaseNames, ShardingValue<Long> shardingValue) { Collection<String> result = new LinkedHashSet<>(databaseNames.size()); for (Long value : shardingValue.getValues()) { for (String tableName : databaseNames) { if (tableName.endsWith(value % 2 + "")) { result.add(tableName); } } } return result; } @Override public Collection<String> doBetweenSharding(Collection<String> databaseNames, ShardingValue<Long> shardingValue) { Collection<String> result = new LinkedHashSet<>(databaseNames.size()); Range<Long> range = (Range<Long>) shardingValue.getValueRange(); for (Long i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) { for (String each : databaseNames) { if (each.endsWith(i % 2 + "")) { result.add(each); } } } return result; } }
分表策略的基本實(shí)現(xiàn),接口:TableShardingAlgorithm
import java.util.Collection; import java.util.LinkedHashSet; import com.dangdang.ddframe.rdb.sharding.api.ShardingValue; import com.dangdang.ddframe.rdb.sharding.api.strategy.table.SingleKeyTableShardingAlgorithm; import com.google.common.collect.Range; /** * Created by fuwei.deng on 2017年5月11日. */ public class ModuloTableShardingAlgorithm implements SingleKeyTableShardingAlgorithm<Long> { @Override public String doEqualSharding(Collection<String> tableNames, ShardingValue<Long> shardingValue) { for (String each : tableNames) { if (each.endsWith(shardingValue.getValue() % 2 + "")) { return each; } } throw new IllegalArgumentException(); } @Override public Collection<String> doInSharding(Collection<String> tableNames, ShardingValue<Long> shardingValue) { Collection<String> result = new LinkedHashSet<>(tableNames.size()); for (Long value : shardingValue.getValues()) { for (String tableName : tableNames) { if (tableName.endsWith(value % 2 + "")) { result.add(tableName); } } } return result; } @Override public Collection<String> doBetweenSharding(Collection<String> tableNames, ShardingValue<Long> shardingValue) { Collection<String> result = new LinkedHashSet<>(tableNames.size()); Range<Long> range = (Range<Long>) shardingValue.getValueRange(); for (Long i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) { for (String each : tableNames) { if (each.endsWith(i % 2 + "")) { result.add(each); } } } return result; } }
至此,分庫(kù)分表的功能已經(jīng)實(shí)現(xiàn)
讀寫分離
讀寫分離需在創(chuàng)建DataSourceRule之前加一層主從數(shù)據(jù)源的創(chuàng)建
// 構(gòu)建讀寫分離數(shù)據(jù)源, 讀寫分離數(shù)據(jù)源實(shí)現(xiàn)了DataSource接口, 可直接當(dāng)做數(shù)據(jù)源處理. // masterDataSource0, slaveDataSource00, slaveDataSource01等為使用DBCP等連接池配置的真實(shí)數(shù)據(jù)源 DataSource masterSlaveDs0 = MasterSlaveDataSourceFactory.createDataSource("ms_0", masterDataSource0, slaveDataSource00, slaveDataSource01); DataSource masterSlaveDs1 = MasterSlaveDataSourceFactory.createDataSource("ms_1", masterDataSource1, slaveDataSource11, slaveDataSource11); // 構(gòu)建分庫(kù)分表數(shù)據(jù)源 Map<String, DataSource> dataSourceMap = new HashMap<>(2); dataSourceMap.put("ms_0", masterSlaveDs0); dataSourceMap.put("ms_1", masterSlaveDs1); // 通過(guò)ShardingDataSourceFactory繼續(xù)創(chuàng)建ShardingDataSource
強(qiáng)制使用主庫(kù)時(shí)
HintManager hintManager = HintManager.getInstance(); hintManager.setMasterRouteOnly(); // 繼續(xù)JDBC操作
強(qiáng)制路由
- 使用ThreadLocal機(jī)制實(shí)現(xiàn),在執(zhí)行數(shù)據(jù)庫(kù)操作之前通過(guò)HintManager改變用于計(jì)算路由的值
- 設(shè)置HintManager的時(shí)候分庫(kù)和分表的策略必須同時(shí)設(shè)置,并且設(shè)置后需要路由的表都需要設(shè)置用于計(jì)算路由的值。比如強(qiáng)制路由后需要操作t_order和t_order_item兩個(gè)表,那么兩個(gè)表的分庫(kù)和分表的策略都需要設(shè)置
HintManager hintManager = HintManager.getInstance(); hintManager.addDatabaseShardingValue("t_order", "user_id", 1L); hintManager.addTableShardingValue("t_order", "order_id", order.getOrderId()); hintManager.addDatabaseShardingValue("t_order_item", "user_id", 1L); hintManager.addTableShardingValue("t_order_item", "order_id", order.getOrderId());
事務(wù)
- sharding-jdbc-transaction實(shí)現(xiàn)柔性事務(wù)(默認(rèn)提供了基于內(nèi)存的事務(wù)日志存儲(chǔ)器和內(nèi)嵌異步作業(yè)),可結(jié)合elastic-job(sharding-jdbc-transaction-async-job)實(shí)現(xiàn)異步柔性事務(wù)
- 沒有與spring結(jié)合使用的方式,需要自己封裝
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java實(shí)現(xiàn)從數(shù)據(jù)庫(kù)導(dǎo)出大量數(shù)據(jù)記錄并保存到文件的方法
這篇文章主要介紹了Java實(shí)現(xiàn)從數(shù)據(jù)庫(kù)導(dǎo)出大量數(shù)據(jù)記錄并保存到文件的方法,涉及Java針對(duì)數(shù)據(jù)庫(kù)的讀取及文件寫入等操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11java實(shí)現(xiàn)PDF轉(zhuǎn)圖片的方法
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)PDF轉(zhuǎn)圖片的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07一文搞懂Java常見的三種代理模式(靜態(tài)代理、動(dòng)態(tài)代理和cglib代理)
Java中常見的三種代理模式是靜態(tài)代理模式、動(dòng)態(tài)代理模式和CGLIB代理模式,本文就來(lái)給大家詳細(xì)的講解一下這三種代理模式,感興趣的小伙伴跟著小編一起來(lái)看看吧2023-08-08Java concurrency線程池之線程池原理(三)_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要為大家詳細(xì)介紹了Java concurrency線程池之線程池原理第三篇,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06