Table splitting based on springboot+sharding jdbc +spring data jpa

Table splitting based on springboot+sharding jdbc +spring data jpa

background

The IOT PC rental project in the charge of the blogger did not consider this aspect in the code design because the product said it did not need to support the multi tenant mode in the design stage. Suddenly, some time ago, gou product said it needed to do this mode. So we have to carry out pre research.

Design ideas

The original idea was to use data table fields as data pseudo isolation (field conditions are added for all operations). In this way, code modification can be reduced. However, considering that the project architecture is relatively simple, only mysql and redis are used for data storage, and there is no time series database or mongodb to store business data. There are some large data tables in mysql, If you only use fields for isolation, it will cause query efficiency problems. so, I plan to use sharding JDBC to divide large tables (of course, you can also divide libraries, but I don't think it's necessary here). Next is the code file demonstration.

code

pom

The following pom leads the package.

    <dependency>
      <groupId>org.apache.shardingsphere</groupId>
      <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
      <version>5.0.0-beta</version>
    </dependency>

yml configuration (key)

The following is about the configuration of shardingsphere and jpa. It depends on their needs. Because it is pre research, this paragraph is not involved. jpa is configured to automatically generate tables and libraries.

spring:
  shardingsphere:
    # Data source configuration
    datasource:
      # Data source name. Multiple data sources are separated by commas
      names: zc #
      zc:
        type: com.zaxxer.hikari.HikariDataSource
        jdbc-url: jdbc:mysql://localhost:3306/zc?createDatabaseIfNotExist=true&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useLegacyDatetimeCode=false&serverTimezone=UTC
        driver-class-name: com.mysql.cj.jdbc.Driver
        username: root
        password: root
    # Rule configuration
    rules:
      sharding:
        tables:
          # Logical table name
          device_log:
            # The line expression identifier can use ${...} or $- > {...}, but the former conflicts with the placeholder of Spring's own property file. Therefore, it is recommended to use $- > {...} in the Spring environment
            actual-data-nodes: zc.device_log_$->{1..3}
    # Table splitting strategy
    table-strategy:
      standard:
        # Partition column name
        sharding-column: company_code
        # Partition algorithm name
        sharding-algorithm-name: table-inline
    # Table primary key algorithm
#    key-generate-strategy:
#      column: id
#      key-generator-name: snowflake
    # Partition algorithm configuration
    sharding-algorithms:
      table-inline:
        # Partition algorithm type
        type: INLINE
        props:
          # Row expression of slicing algorithm
          algorithm-expression: device_log_$->{company_code}
#    # Distributed sequence algorithm configuration
#    key-generators:
#      snowflake:
#        # Distributed sequence algorithm (SNOWFLAKE algorithm: SNOWFLAKE; UUID: UUID)
#        type: SNOWFLAKE
#        # Attribute configuration of distributed sequence algorithm
#        props:
#          # Unique identification of the working machine
#          worker-id: 123
  jpa:
    database: mysql
    database-platform: org.hibernate.dialect.MySQL57Dialect
    hibernate:
      ddl-auto: update
    properties:
      hibernate:
        jdbc:
          time_zone: UTC
  messages:
    encoding: UTF-8

Test code

The test code is shown below. When inserting, the table will be inserted according to the configured code, and findAll will query all tables, but the local test is a little slow. This operation should be avoided. Querying data according to code will also query the corresponding table.

        List<String> merchantList = Lists.newArrayList("1", "2", "3");
        // Insert 20 pieces of data
        for (int i = 0; i < 20; i++) {
            DeviceLog log = new DeviceLog();
            log.setSn("9999" + i);
            log.setCompanyCode(merchantList.get(new Random().nextInt(merchantList.size())));
            log.setCreateTime(DateUtils.format(new Date(), DateUtil.pattern_yMdHms));
            log.setTmxData("{}");
            log.setShanzuData("{}");
            deviceLogRepository.save(log);
        }
        // Query all data
        List<DeviceLog> deviceLogs = deviceLogRepository.findAll();
        // Query data according to code
        List<DeviceLog> deviceLogs1 = deviceLogRepository.queryDeviceLogByCode(merchantList.get(new Random().nextInt(merchantList.size())));

sql of querydevice logbycode:

    @Query(value = "select * from device_log c where  c.company_code = :companyCode",nativeQuery = true)
    List<DeviceLog> queryDeviceLogByCode(@Param("companyCode") String companyCode);

Pit encountered during pre research

1. At the beginning, the sharding version was too low. Both 3.x and 4.x encountered Unsupported Date type:class java.lang.String error. Upgrade to version 5.0.0-beta. As for what other articles said about turning off log sql printing, it was nonsense.
Specific issue:https://github.com/apache/shardingsphere/issues/12822
2. Due to different sharding version points, the configuration files will be different, and the configuration needs to be modified according to the version.

Keywords: Java Database Spring

Added by nor0101 on Thu, 30 Sep 2021 04:56:37 +0300