欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

spring boot使用sharding jdbc的配置方式

程序员文章站 2023-12-21 08:13:40
本文介绍了spring boot使用sharding jdbc的配置方式,分享给大家,具体如下: 说明 要排除datasourceautoconfiguration,否...

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

官方文档:

步骤

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

@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操作

强制路由

  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结合使用的方式,需要自己封装

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

上一篇:

下一篇: