本文介绍了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