spring boot使用sharding jdbc的配置方式


声明:本文转载自https://my.oschina.net/dengfuwei/blog/1595151,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

说明

  • 要排除DataSourceAutoConfiguration,否则多数据源无法配置
@SpringBootApplication @EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) public class Application {      public static void main(String[] args) {     	SpringApplication.run(Application.class, args);     } 	 } 

步骤

  • 配置多个数据源,数据源的名称最好要有一定的规则,方便配置分库的计算规则
@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管理,并且可以设置默认的数据源,当表没有配置分库规则时会使用默认的数据源
@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"); } 
  • 配置数据源策略和表策略,具体策略需要自己实现
@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会使用此数据源
@Bean("dataSource") public DataSource shardingDataSource(ShardingRule shardingRule){     return ShardingDataSourceFactory.createDataSource(shardingRule); } 
  • 需要手动配置事务管理器(原因未知)
//需要手动声明配置事务 @Bean public DataSourceTransactionManager transactitonManager(@Qualifier("dataSource") DataSource dataSource){     return new DataSourceTransactionManager(dataSource); } 
  • 分库策略的简单实现,接口: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;     }  } 
  • 分表策略的基本实现,接口: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;     }  } 
  • 至此,分库分表的功能已经实现

读写分离

  • 读写分离需在创建DataSourceRule之前加一层主从数据源的创建
// 构建读写分离数据源, 读写分离数据源实现了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 
  • 强制使用主库时
HintManager hintManager = HintManager.getInstance(); hintManager.setMasterRouteOnly(); // 继续JDBC操作 

强制路由

  • 使用ThreadLocal机制实现,在执行数据库操作之前通过HintManager改变用于计算路由的值
  • 设置HintManager的时候分库和分表的策略必须同时设置,并且设置后需要路由的表都需要设置用于计算路由的值。比如强制路由后需要操作t_order和t_order_item两个表,那么两个表的分库和分表的策略都需要设置
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结合使用的方式,需要自己封装

本文发表于2017年12月26日 22:32
(c)注:本文转载自https://my.oschina.net/dengfuwei/blog/1595151,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 1942 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1