Location>code7788 >text

sharding-jdbc Compatible with MybatisPlus Dynamic Data Source

Popularity:227 ℃/2024-07-29 16:03:47

Background:The previous project to do read-write separation when using MybatisPlus dynamic data to do, a lot of places to use the @DS directly specify the read or write library to achieve the business; with the table data volume is getting bigger and bigger, and now intends to be a relatively large table for the level of splitting, ready to use the ShardingJDBC to achieve, but found that the two together is not so smooth, the Internet! Most of the articles are directly to the entire Sharding data source as a data source MybatisPlus, then the original @DS above the specified data source can not be directly used Sharding library and other logic, so I studied the source code, the realization of this logic, to the back of the need for friends to provide a case, to avoid wasting unnecessary time!

I. Version Selection

There are currently two main versions of ShardingJDBC, an early version of ShardingJDBC and ShardingSphere-JDBC from the ShardingSphere project

  • Sharding-JDBC: Sharding-JDBC was originally released in 2016 by the then project sponsors. It was first introduced as a lightweight JDBC tier solution designed to solve the problem of database sharding and read/write separation.
  • ShardingSphere : The ShardingSphere project evolved from the Sharding-JDBC project and was officially released in 2018.Apache ShardingSphere is dedicated to building a more complete distributed database management ecosystem and includes Sharding-JDBC, Sharding-Proxy, and Sharding-Sidecar.

The standalone ShardingJDBC has been discontinued, and the most used version is 4.1.1.

<dependency>
    <groupId></groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>4.1.1</version>
</dependency>

ShardingSphere project has been in the update iteration , ShardingSphere-JDBC is through the ShardingJDBC update iteration over , in the original code based on some optimization and new features to join , for the developer , mainly the configuration of the parameters have some adjustments . But the role of the parameters and the configuration of the same way as before;

Here I am using ShardingSphere-JDBC 5.2.1 directly for the convenience of new features that will be used later.

Official Help Documentation/read/shardingsphere-5.1.0-zh/

<dependency>
	<groupId></groupId>
	<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
	<version>5.2.1</version>
</dependency>

II. Project dependencies

The full Maven dependencies for the case are listed below:

    <dependencies>
        <dependency>
            <groupId></groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId></groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId></groupId>
            <artifactId>HikariCP</artifactId>
            <version>3.4.5</version>
        </dependency>

        <dependency>
            <groupId></groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.0</version>
        </dependency>

        <!-- read-write separation -->
        <dependency>
            <groupId></groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>3.3.2</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>

        <!--Shardingjdbc-->
        <dependency>
            <groupId></groupId>
            <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
            <version>5.2.1</version>
            <exclusions>
                <exclusion>
                    <groupId></groupId>
                    <artifactId>snakeyaml</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- Add the correct version of the SnakeYAML shardingsphere-jdbcThere's a problem with the dependency version in there,will report an error-->
        <dependency>
            <groupId></groupId>
            <artifactId>snakeyaml</artifactId>
            <version>1.33</version>
        </dependency>

        <dependency>
            <groupId></groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

III. Parameter Configuration

configure

server:
  port: 8080

mybatis-plus:
  mapper-locations: classpath*:mybatis/*.xml
  type-aliases-package:
  configuration:
    map-underscore-to-camel-case: false
    log-impl:

spring:
  application:
    name: sharding-jdbc-test
  sharding-sphere:
    datasource:
      names: master,write,read,read2
      master:
        type:
        driver-class-name:
        jdbc-url: jdbc:mysql://127.0.0.1:3306/game_dev?characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&autoReconnect=true&serverTimezone=Asia/Shanghai
        username: root
        password: 123456
      write:
        type:
        driver-class-name:
        jdbc-url: jdbc:mysql://127.0.0.1:3306/game_dev?characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&autoReconnect=true&serverTimezone=Asia/Shanghai
        username: root
        password: 123456
      read:
        type:
        driver-class-name:
        jdbc-url: jdbc:mysql://127.0.0.1:3306/game_dev_read?characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&autoReconnect=true&serverTimezone=Asia/Shanghai
        username: root
        password: 123456
      read2:
        type:
        driver-class-name:
        jdbc-url: jdbc:mysql://127.0.0.1:3306/game_dev_read?characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&autoReconnect=true&serverTimezone=Asia/Shanghai
        username: root
        password: 123456
    rules:
      sharding:
        tables:
          team_msg:
		  ## Here.customer-dsis the name of the data source for the read/write separation configured below
            actual-data-nodes: customer-ds.team_msg_${0..1}
            table-strategy:
              standard:
                sharding-column: id
                sharding-algorithm-name: msg-id # corresponds to the followingsharding-algorithms
        sharding-algorithms:
          ## Note the name here(for examplemsg-id)No underlining,The following parameters will not be loaded, resulting in a startup error
          msg-id:
            type: INLINE
            props:
			## utilizationidmodulus extraction algorithm
              algorithm-expression: team_msg_${id % 2}
	 ## Read/Write Separation Related
      readwrite-splitting:
        data-sources:
          customer-ds:
            load-balancer-name: customer-lb
            static-strategy:
              write-data-source-name: master
              read-data-source-names: read,read2,write
        load-balancers:
            customer-lb:
			    ## utilization自定义的复杂均衡算法
                type: CUSTOM
    props:
      # Show real after processingsql
      sql-show: true

Code Configuration

The most critical configuration is the need to register the MybatisPlus data source as a data source using shardingsphere-jdbc, and to ensure that the name of the data source and the original MybatisPlus data source is consistent, shardingSphereDataSource in fact, there is a Map to save all the configurations in the data source, here is mainly to facilitate the subsequent use of @DS to do dynamic data source switching, so the same ShardingSphere database is registered as a dynamic data source for four, to avoid the use of @DS can not find the corresponding data source;

import ;
import ;
import ;
import ;
import ;
import .;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;

import ;
import ;
import ;
import ;
import ;

/**
 * <p>
 * <p>
 * <p/>
 *
 * @author luowj
 * @version 1.0
 * @since 2024/7/22 18:41
 */
@Configuration
@AutoConfigureBefore({, })
public class MyDataSourceConfiguration {

    /**
     * mybatisplus Dynamic Data Source Configuration Items
     */
    @Autowired
    private DynamicDataSourceProperties properties;

    /**
     * shardingjdbcdata source
     */
    @Lazy
    @Resource(name = "shardingSphereDataSource")
    private AbstractDataSourceAdapter shardingSphereDataSource;

    @Value("${}")
    private String shardingDataSourceNames;

    /**
     * Registering Dynamic Data Sources It's very critical here.,Because we need to use the@DSAnnotation Configuration Dynamic Selection of Data Sources,同上又要让选择data source使用shardingjdbcdata source
     * the reason why,这里需要动态的把所有data source都注册为 shardingjdbcdata source
     */
    @Bean
    public DynamicDataSourceProvider dynamicDataSourceProvider() {
        if ((shardingDataSourceNames)) {
            throw new RuntimeException("configure Cannot be empty");
        }
        String[] names = (",");
        return new AbstractDataSourceProvider() {
            @Override
            public Map<String, DataSource> loadDataSources() {
                Map<String, DataSource> dataSourceMap = new HashMap<>();
                (names).forEach(name -> (name, shardingSphereDataSource));
                return dataSourceMap;
            }
        };
    }

    /**
     * Setting a dynamic data source as the preferred data source
     */
    @Primary
    @Bean
    public DataSource dataSource(DynamicDataSourceProvider dynamicDataSourceProvider) {
        DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();
        (());
        (());
        (());
        (dynamicDataSourceProvider);
        dataSource.setP6spy(properties.getP6spy());
        (());
        return dataSource;
    }
}

Customizing Complex Equalization Algorithms in ShardingSphere

Load balancing in shardingsphere requires the implementation of the ReadQueryLoadBalanceAlgorithm interface and the return of a customized algorithm name in the getType method, which officially comes with RoundRobinReadQueryLoadBalanceAlgorithm, RandomReadQueryLoadBalanceAlgorithm and so on. RandomReadQueryLoadBalanceAlgorithm, etc. Here we must customize the algorithm to be compatible with the @DS annotation to achieve the freedom to switch the data source;

ShardingSphere is loaded using the SPI mechanism, and the corresponding loading source code section is as follows:

image

So if we want our custom ReadQueryLoadBalanceAlgorithm class to take effect, we need to create a file in the services folder of our project's META-INF and populate it with the custom class

The configuration in the source code is as follows:
image

Then we follow the configuration of the source code to create it directly in our own project

image

Final custom implementation of CustomLoadBalanceAlgorithm


public class CustomLoadBalanceAlgorithm implements ReadQueryLoadBalanceAlgorithm {
    private Properties props;

    public CustomLoadBalanceAlgorithm() {

    }

    @Override
    public void init(Properties props) {
         = props;
    }

    /**
     * Getting the data source
     *
     * @param name Data source name(ShardingJDBCapplied)
     * @param writeDataSourceName 写Data source name
     * @param readDataSourceNames 所有配置的复杂均衡center读Data source name
     * @param context Transaction Context Object,Accessible() Determining whether a transaction is required,This can be used to determine if the Write Data Source
     * @return
     */
    @Override
    public String getDataSource(String name, String writeDataSourceName, List<String> readDataSourceNames, TransactionConnectionContext context) {
        // Get currentMybatisPlusSpecified data source
        String dsKey = ();
        if ((dsKey)) {
            if ((dsKey)) {
                return dsKey;
            }
            if ((dsKey)) {
                return dsKey;
            }
            throw new RuntimeException("@DS misconfiguration,Current Data Source[" + dsKey + "](euphemism) pass awaySharingJDBCList of data sources[" + readDataSourceNames + "]center");
        }
        return writeDataSourceName;
    }

    @Override
    public String getType() {
        return "CUSTOM";
    }

    @Override
    public boolean isDefault() {
        return true;
    }

    @Override
    @Generated
    public Properties getProps() {
        return ;
    }
}

V. Source Code

Gitee: /luowenjie98/sharing-sphere-mybatisplus-demo

Please give me a STAR if you find it helpful, thank you very much !