首页 > 开发 > Java > 正文

spring boot使用sharding jdbc的配置方式

2024-07-13 10:15:36
字体:
来源:转载
供稿:网友

本文介绍了spring boot使用sharding jdbc的配置方式,分享给大家,具体如下:

说明

要排除DataSourceAutoConfiguration,否则多数据源无法配置

@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

步骤

配置多个数据源,数据源的名称最好要有一定的规则,方便配置分库的计算规则

@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管理,并且可以设置默认的数据源,当表没有配置分库规则时会使用默认的数据源

@Beanpublic 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");}

配置数据源策略和表策略,具体策略需要自己实现

@Beanpublic 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);}

需要手动配置事务管理器(原因未知)

//需要手动声明配置事务@Beanpublic 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操作

强制路由

  1. 使用ThreadLocal机制实现,在执行数据库操作之前通过HintManager改变用于计算路由的值
  2. 设置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());

事务

  1. sharding-jdbc-transaction实现柔性事务(默认提供了基于内存的事务日志存储器和内嵌异步作业),可结合elastic-job(sharding-jdbc-transaction-async-job)实现异步柔性事务
  2. 没有与spring结合使用的方式,需要自己封装

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VeVb武林网。


注:相关教程知识阅读请移步到JAVA教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表