本文介紹了spring boot使用sharding jdbc的配置方式,分享給大家,具體如下:
說明
要排除DataSourceAutoConfiguration,否則多數據源無法配置
1
2
3
4
5
6
7
8
9
|
@SpringBootApplication @EnableAutoConfiguration (exclude={DataSourceAutoConfiguration. class }) public class Application { public static void main(String[] args) { SpringApplication.run(Application. class , args); } } |
配置的多個數據源交給sharding-jdbc管理,sharding-jdbc創建一個DataSource數據源提供給mybatis使用
官方文檔:http://shardingjdbc.io/index_zh.html
步驟
配置多個數據源,數據源的名稱最好要有一定的規則,方便配置分庫的計算規則
1
2
3
4
5
6
7
8
9
10
11
|
@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(); } |
配置數據源規則,即將多個數據源交給sharding-jdbc管理,并且可以設置默認的數據源,當表沒有配置分庫規則時會使用默認的數據源
1
2
3
4
5
6
7
8
|
@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" ); } |
配置數據源策略和表策略,具體策略需要自己實現
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
@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(); //綁定表策略,在查詢時會使用主表策略計算路由的數據源,因此需要約定綁定表策略的表的規則需要一致,可以一定程度提高效率 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(); } |
創建sharding-jdbc的數據源DataSource,MybatisAutoConfiguration會使用此數據源
1
2
3
4
|
@Bean ( "dataSource" ) public DataSource shardingDataSource(ShardingRule shardingRule){ return ShardingDataSourceFactory.createDataSource(shardingRule); } |
需要手動配置事務管理器(原因未知)
1
2
3
4
5
|
//需要手動聲明配置事務 @Bean public DataSourceTransactionManager transactitonManager( @Qualifier ( "dataSource" ) DataSource dataSource){ return new DataSourceTransactionManager(dataSource); } |
分庫策略的簡單實現,接口:DatabaseShardingAlgorithm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
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; } } |
分表策略的基本實現,接口:TableShardingAlgorithm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
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; } } |
至此,分庫分表的功能已經實現
讀寫分離
讀寫分離需在創建DataSourceRule之前加一層主從數據源的創建
1
2
3
4
5
6
7
8
9
10
11
12
13
|
// 構建讀寫分離數據源, 讀寫分離數據源實現了DataSource接口, 可直接當做數據源處理. // masterDataSource0, slaveDataSource00, slaveDataSource01等為使用DBCP等連接池配置的真實數據源 DataSource masterSlaveDs0 = MasterSlaveDataSourceFactory.createDataSource( "ms_0" , masterDataSource0, slaveDataSource00, slaveDataSource01); DataSource masterSlaveDs1 = MasterSlaveDataSourceFactory.createDataSource( "ms_1" , masterDataSource1, slaveDataSource11, slaveDataSource11); // 構建分庫分表數據源 Map<String, DataSource> dataSourceMap = new HashMap<>( 2 ); dataSourceMap.put( "ms_0" , masterSlaveDs0); dataSourceMap.put( "ms_1" , masterSlaveDs1); // 通過ShardingDataSourceFactory繼續創建ShardingDataSource |
強制使用主庫時
1
2
3
|
HintManager hintManager = HintManager.getInstance(); hintManager.setMasterRouteOnly(); // 繼續JDBC操作 |
強制路由
- 使用ThreadLocal機制實現,在執行數據庫操作之前通過HintManager改變用于計算路由的值
- 設置HintManager的時候分庫和分表的策略必須同時設置,并且設置后需要路由的表都需要設置用于計算路由的值。比如強制路由后需要操作t_order和t_order_item兩個表,那么兩個表的分庫和分表的策略都需要設置
1
2
3
4
5
|
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()); |
事務
- sharding-jdbc-transaction實現柔性事務(默認提供了基于內存的事務日志存儲器和內嵌異步作業),可結合elastic-job(sharding-jdbc-transaction-async-job)實現異步柔性事務
- 沒有與spring結合使用的方式,需要自己封裝
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://my.oschina.net/dengfuwei/blog/1595151