【Sharding Sphere、Spring Boot】Spring Boot整合Sharding Sphere Jdbc(5.0.0):数据分片

一、Sharding Sphere基本介绍

官网链接推荐:跳转官网 | 5.0.0中文文档 | 数据分片介绍

二、Spring Boot整合Sharding Sphere Jdbc

1、数据库准备

cyun_log_0数据库

CREATE DATABASE `cyun_log_0` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

USE `cyun_log_0`;

DROP TABLE IF EXISTS `t_sys_log`;
CREATE TABLE `t_sys_log`
(
    `id`               varchar(32) NOT NULL COMMENT '日志ID',
    `application_name` varchar(32) NOT NULL COMMENT '服务名称',
    `log_type`         int(2)      NOT NULL DEFAULT '0' COMMENT '日志类型(0-未知、1-登录日志、2-操作日志、3-定时任务日志)',
    `operate_type`     int(2)               DEFAULT NULL COMMENT '操作类型(0-未知、1-查询、2-添加、3-更新、4-删除、5-导入、6-导出)',
    `log_content`      varchar(1000)        DEFAULT NULL COMMENT '日志描述信息',
    `ip`               varchar(100)         DEFAULT NULL COMMENT 'IP',
    `method`           varchar(500)         DEFAULT NULL COMMENT '请求java方法',
    `request_url`      varchar(255)         DEFAULT NULL COMMENT '请求路径',
    `request_param`    longtext COMMENT '请求参数',
    `request_type`     varchar(10)          DEFAULT NULL COMMENT '请求类型',
    `cost_time`        bigint(20)           DEFAULT NULL COMMENT '耗时(单位:毫秒)',
    `create_by`        varchar(32)          DEFAULT NULL COMMENT '创建人',
    `create_time`      datetime             DEFAULT NULL COMMENT '创建时间',
    `update_by`        varchar(32)          DEFAULT NULL COMMENT '更新人',
    `update_time`      datetime             DEFAULT NULL COMMENT '更新时间',
    PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4 COMMENT ='系统日志表';

DROP TABLE IF EXISTS `t_sys_log_2022_04`;
CREATE TABLE `t_sys_log_2022_04`
(
    `id`               varchar(32) NOT NULL COMMENT '日志ID',
    `application_name` varchar(32) NOT NULL COMMENT '服务名称',
    `log_type`         int(2)      NOT NULL DEFAULT '0' COMMENT '日志类型(0-未知、1-登录日志、2-操作日志、3-定时任务日志)',
    `operate_type`     int(2)               DEFAULT NULL COMMENT '操作类型(0-未知、1-查询、2-添加、3-更新、4-删除、5-导入、6-导出)',
    `log_content`      varchar(1000)        DEFAULT NULL COMMENT '日志描述信息',
    `ip`               varchar(100)         DEFAULT NULL COMMENT 'IP',
    `method`           varchar(500)         DEFAULT NULL COMMENT '请求java方法',
    `request_url`      varchar(255)         DEFAULT NULL COMMENT '请求路径',
    `request_param`    longtext COMMENT '请求参数',
    `request_type`     varchar(10)          DEFAULT NULL COMMENT '请求类型',
    `cost_time`        bigint(20)           DEFAULT NULL COMMENT '耗时(单位:毫秒)',
    `create_by`        varchar(32)          DEFAULT NULL COMMENT '创建人',
    `create_time`      datetime             DEFAULT NULL COMMENT '创建时间',
    `update_by`        varchar(32)          DEFAULT NULL COMMENT '更新人',
    `update_time`      datetime             DEFAULT NULL COMMENT '更新时间',
    PRIMARY KEY (`id`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4 COMMENT ='系统日志表';

DROP TABLE IF EXISTS `t_sys_log_2022_05`;
CREATE TABLE `t_sys_log_2022_05`
(
    `id`               varchar(32) NOT NULL COMMENT '日志ID',
    `application_name` varchar(32) NOT NULL COMMENT '服务名称',
    `log_type`         int(2)      NOT NULL DEFAULT '0' COMMENT '日志类型(0-未知、1-登录日志、2-操作日志、3-定时任务日志)',
    `operate_type`     int(2)               DEFAULT NULL COMMENT '操作类型(0-未知、1-查询、2-添加、3-更新、4-删除、5-导入、6-导出)',
    `log_content`      varchar(1000)        DEFAULT NULL COMMENT '日志描述信息',
    `ip`               varchar(100)         DEFAULT NULL COMMENT 'IP',
    `method`           varchar(500)         DEFAULT NULL COMMENT '请求java方法',
    `request_url`      varchar(255)         DEFAULT NULL COMMENT '请求路径',
    `request_param`    longtext COMMENT '请求参数',
    `request_type`     varchar(10)          DEFAULT NULL COMMENT '请求类型',
    `cost_time`        bigint(20)           DEFAULT NULL COMMENT '耗时(单位:毫秒)',
    `create_by`        varchar(32)          DEFAULT NULL COMMENT '创建人',
    `create_time`      datetime             DEFAULT NULL COMMENT '创建时间',
    `update_by`        varchar(32)          DEFAULT NULL COMMENT '更新人',
    `update_time`      datetime             DEFAULT NULL COMMENT '更新时间',
    PRIMARY KEY (`id`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4 COMMENT ='系统日志表';

cyun_log_1数据库

CREATE DATABASE `cyun_log_1` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

USE `cyun_log_1`;

DROP TABLE IF EXISTS `t_sys_log`;
CREATE TABLE `t_sys_log`
(
    `id`               varchar(32) NOT NULL COMMENT '日志ID',
    `application_name` varchar(32) NOT NULL COMMENT '服务名称',
    `log_type`         int(2)      NOT NULL DEFAULT '0' COMMENT '日志类型(0-未知、1-登录日志、2-操作日志、3-定时任务日志)',
    `operate_type`     int(2)               DEFAULT NULL COMMENT '操作类型(0-未知、1-查询、2-添加、3-更新、4-删除、5-导入、6-导出)',
    `log_content`      varchar(1000)        DEFAULT NULL COMMENT '日志描述信息',
    `ip`               varchar(100)         DEFAULT NULL COMMENT 'IP',
    `method`           varchar(500)         DEFAULT NULL COMMENT '请求java方法',
    `request_url`      varchar(255)         DEFAULT NULL COMMENT '请求路径',
    `request_param`    longtext COMMENT '请求参数',
    `request_type`     varchar(10)          DEFAULT NULL COMMENT '请求类型',
    `cost_time`        bigint(20)           DEFAULT NULL COMMENT '耗时(单位:毫秒)',
    `create_by`        varchar(32)          DEFAULT NULL COMMENT '创建人',
    `create_time`      datetime             DEFAULT NULL COMMENT '创建时间',
    `update_by`        varchar(32)          DEFAULT NULL COMMENT '更新人',
    `update_time`      datetime             DEFAULT NULL COMMENT '更新时间',
    PRIMARY KEY (`id`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4 COMMENT ='系统日志表';

DROP TABLE IF EXISTS `t_sys_log_2022_04`;
CREATE TABLE `t_sys_log_2022_04`
(
    `id`               varchar(32) NOT NULL COMMENT '日志ID',
    `application_name` varchar(32) NOT NULL COMMENT '服务名称',
    `log_type`         int(2)      NOT NULL DEFAULT '0' COMMENT '日志类型(0-未知、1-登录日志、2-操作日志、3-定时任务日志)',
    `operate_type`     int(2)               DEFAULT NULL COMMENT '操作类型(0-未知、1-查询、2-添加、3-更新、4-删除、5-导入、6-导出)',
    `log_content`      varchar(1000)        DEFAULT NULL COMMENT '日志描述信息',
    `ip`               varchar(100)         DEFAULT NULL COMMENT 'IP',
    `method`           varchar(500)         DEFAULT NULL COMMENT '请求java方法',
    `request_url`      varchar(255)         DEFAULT NULL COMMENT '请求路径',
    `request_param`    longtext COMMENT '请求参数',
    `request_type`     varchar(10)          DEFAULT NULL COMMENT '请求类型',
    `cost_time`        bigint(20)           DEFAULT NULL COMMENT '耗时(单位:毫秒)',
    `create_by`        varchar(32)          DEFAULT NULL COMMENT '创建人',
    `create_time`      datetime             DEFAULT NULL COMMENT '创建时间',
    `update_by`        varchar(32)          DEFAULT NULL COMMENT '更新人',
    `update_time`      datetime             DEFAULT NULL COMMENT '更新时间',
    PRIMARY KEY (`id`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4 COMMENT ='系统日志表';

DROP TABLE IF EXISTS `t_sys_log_2022_05`;
CREATE TABLE `t_sys_log_2022_05`
(
    `id`               varchar(32) NOT NULL COMMENT '日志ID',
    `application_name` varchar(32) NOT NULL COMMENT '服务名称',
    `log_type`         int(2)      NOT NULL DEFAULT '0' COMMENT '日志类型(0-未知、1-登录日志、2-操作日志、3-定时任务日志)',
    `operate_type`     int(2)               DEFAULT NULL COMMENT '操作类型(0-未知、1-查询、2-添加、3-更新、4-删除、5-导入、6-导出)',
    `log_content`      varchar(1000)        DEFAULT NULL COMMENT '日志描述信息',
    `ip`               varchar(100)         DEFAULT NULL COMMENT 'IP',
    `method`           varchar(500)         DEFAULT NULL COMMENT '请求java方法',
    `request_url`      varchar(255)         DEFAULT NULL COMMENT '请求路径',
    `request_param`    longtext COMMENT '请求参数',
    `request_type`     varchar(10)          DEFAULT NULL COMMENT '请求类型',
    `cost_time`        bigint(20)           DEFAULT NULL COMMENT '耗时(单位:毫秒)',
    `create_by`        varchar(32)          DEFAULT NULL COMMENT '创建人',
    `create_time`      datetime             DEFAULT NULL COMMENT '创建时间',
    `update_by`        varchar(32)          DEFAULT NULL COMMENT '更新人',
    `update_time`      datetime             DEFAULT NULL COMMENT '更新时间',
    PRIMARY KEY (`id`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4 COMMENT ='系统日志表';

注意:使用Mybatis自动生成映射文件,只需要生成t_sys_log的即可,下文配置的就是t_sys_log

2、pom依赖

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

3、application.yml配置


# ShardingSphere 使用本地数据源
spring:
  main:
    allow-bean-definition-overriding: true
  shardingsphere:
    datasource:
      # 数据源
      names: db0,db1
      # 日志类型:未知、操作日志
      db0:
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:7000/cyun_log_0?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
        username: root
        password: root
        type: com.zaxxer.hikari.HikariDataSource
      # 日志类型:登录日志、定时任务日志
      db1:
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:7000/cyun_log_1?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
        username: root
        password: root
        type: com.zaxxer.hikari.HikariDataSource
    # 使用模式,支持三种模式:内存模式、单机模式、集群模式
    mode:
      type: Memory
    props:
      # 打印sql
      sql-show: true
    # 规则
    rules:
      sharding:
        # 算法
        sharding-algorithms:
          t-log-type-inline:
            props:
              # 表达式
              algorithm-expression: db$->{log_type % 2}
            # 行表达式
            type: inline
          sys-log-date-algorithms:
            # 自定义算法
            type: sysLogDateAlgorithm
        # 表格配置
        tables:
          # 此配置为自己编写sql时所使用的表
          t_sys_log:
            actual-data-nodes: db${[0,1]}.t_sys_log,db${[0,1]}.t_sys_log_2022_0${4..5}
            # 数据库策略
            database-strategy:
              standard:
                sharding-algorithm-name: t-log-type-inline
                sharding-column: log_type
            # 表策略
            table-strategy:
              standard:
                # 自定义算法
                sharding-algorithm-name: sys-log-date-algorithms
                sharding-column: create_time

4、自定义日期算法

创建类SysLogDateAlgorithm实现StandardShardingAlgorithm接口

package com.cyun.log.config.algorithm;

import com.google.common.collect.Range;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;
import org.springframework.stereotype.Component;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Set;
import java.util.TreeSet;

/**
 * 自定义按月分表算法
 *
 * @author Panfu.he
 */
@Slf4j
@Component
public class SysLogDateAlgorithm implements StandardShardingAlgorithm<Date> {

    private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy_MM");

    /**
     * 精准分片
     *
     * @param availableTargetNames 表信息
     * @param preciseShardingValue 字段内容信息
     * @return
     */
    @Override
    public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Date> preciseShardingValue) {
        final String yearMonth = sdf.format(preciseShardingValue.getValue());
        // 找到对应得表格
        for (String tableName : availableTargetNames) {
            if (tableName.endsWith(yearMonth)) {
                log.info("############### (sharding-jdbc分表)最终匹配表名:{} ###############", tableName);
                return tableName;
            }
        }
        return (String) availableTargetNames.toArray()[0];
    }

    /**
     * 范围分片
     *
     * @param availableTargetNames 表信息
     * @param rangeShardingValue   字段内容信息
     * @return
     */
    @Override
    public Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<Date> rangeShardingValue) {
        final Range<Date> valueRange = rangeShardingValue.getValueRange();
        final String yearMonth1 = sdf.format(valueRange.lowerEndpoint());
        final String yearMonth2 = sdf.format(valueRange.upperEndpoint());

        // 找到对应得表格
        Set<String> tableNames = new TreeSet<>();
        for (String tableName : availableTargetNames) {
            if (tableName.endsWith(yearMonth1) || tableName.endsWith(yearMonth2)) {
                log.info("############### (sharding-jdbc分表)最终匹配表名:{} ###############", tableName);
                tableNames.add(tableName);
            }
        }
        return tableNames;
    }

    @Override
    public void init() {

    }

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

配置SPI:在资源目录下创建META-INF.services目录 -> 创建文件org.apache.shardingsphere.sharding.spi.ShardingAlgorithm。在文件类配置SysLogDateAlgorithm
在这里插入图片描述
在这里插入图片描述

5、展示

在这里插入图片描述

三、Spring Boot整合Sharding Sphere Jdbc支持未分表的数据源(多数据源配置)

1、新增pom依赖

		<!-- druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.22</version>
        </dependency>

        <!-- 动态数据源 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>3.2.1</version>
        </dependency>

2、application.yml配置,需注意Sharding Sphere Jdbc单数据源配置数据库地址使用的是jdbc-url,而多数据直接使用url


spring:
  datasource:
    # 可以先在这里配置好通用的配置,比如
    druid:
      initial-size: 10
      max-active: 100
      min-idle: 3
      max-wait: 5000
      pool-prepared-statements: true
      max-pool-prepared-statement-per-connection-size: 100
    #dynamic开始多数据源配置
    dynamic:
      datasource:
        master:  # 数据源的名字:master
          username: root
          password: root
          driver-class-name: com.mysql.jdbc.Driver
          url: jdbc:mysql://localhost:7000/cyun_log?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
      primary: master
  shardingsphere:
    datasource:
      # 数据源
      names: db0,db1
      # 日志类型:未知、操作日志
      db0:
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:7000/cyun_log_0?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
        username: root
        password: root
        type: com.alibaba.druid.pool.DruidDataSource
      # 日志类型:登录日志、定时任务日志
      db1:
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:7000/cyun_log_1?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
        username: root
        password: root
        type: com.alibaba.druid.pool.DruidDataSource
    # 使用模式,支持三种模式:内存模式、单机模式、集群模式
    mode:
      type: Memory
    props:
      # 打印sql
      sql-show: true
    # 规则
    rules:
      sharding:
        # 算法
        sharding-algorithms:
          t-log-type-inline:
            props:
              # 表达式
              algorithm-expression: db$->{log_type % 2}
            # 行表达式
            type: inline
          sys-log-date-algorithms:
            # 自定义算法
            type: sysLogDateAlgorithm
        # 表格配置
        tables:
          # 此配置为自己编写sql时所使用的表
          t_sys_log:
            actual-data-nodes: db${[0,1]}.t_sys_log,db${[0,1]}.t_sys_log_2022_0${4..5}
            # 数据库策略
            database-strategy:
              standard:
                sharding-algorithm-name: t-log-type-inline
                sharding-column: log_type
            # 表策略
            table-strategy:
              standard:
                sharding-algorithm-name: sys-log-date-algorithms
                sharding-column: create_time

3、动态数据源配置

package com.cyun.log.config;

import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.provider.AbstractDataSourceProvider;
import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
import org.apache.shardingsphere.driver.jdbc.adapter.AbstractDataSourceAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Map;


/**
 * 动态数据源配置:
 * 使用{@link com.baomidou.dynamic.datasource.annotation.DS}注解,切换数据源
 *
 * @author He PanFu
 * @date 2022-04-14 16:45:26
 */
@Configuration
@AutoConfigureBefore({DynamicDataSourceAutoConfiguration.class, SpringBootConfiguration.class})
public class DataSourceConfiguration {

    /**
     * 分表数据源名称
     */
    private static final String SHARDING_DATA_SOURCE_NAME = "sharding_sphere";
    /**
     * 动态数据源配置项
     */
    @Resource
    private DynamicDataSourceProperties properties;

    /**
     * Sharding Sphere Jdbc有四种数据源,需要根据业务注入不同的数据源
     * <p>
     * 1. 未使用分片, 脱敏的名称(默认): shardingDataSource;
     * 2. 主从数据源: masterSlaveDataSource;
     * 3. 脱敏数据源:encryptDataSource;
     * 4. 影子数据源:shadowDataSource
     */
    @Lazy
    @Resource
    AbstractDataSourceAdapter shardingDataSource;

    @Bean
    public DynamicDataSourceProvider dynamicDataSourceProvider() {
        Map<String, DataSourceProperty> datasourceMap = properties.getDatasource();
        return new AbstractDataSourceProvider() {
            @Override
            public Map<String, DataSource> loadDataSources() {
                Map<String, DataSource> dataSourceMap = createDataSourceMap(datasourceMap);
                // 将 Sharding Sphere Jdbc 管理的数据源也交给动态数据源管理
                dataSourceMap.put(SHARDING_DATA_SOURCE_NAME, shardingDataSource);
                return dataSourceMap;
            }
        };
    }

    /**
     * 将动态数据源设置为首选的
     * 当spring存在多个数据源时, 自动注入的是首选的对象
     * 设置为主要的数据源之后,就可以支持Sharding Sphere Jdbc原生的配置方式了
     *
     * @return 数据源
     */
    @Primary
    @Bean
    public DataSource dataSource(DynamicDataSourceProvider dynamicDataSourceProvider) {
        DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();
        dataSource.setPrimary(properties.getPrimary());
        dataSource.setStrict(properties.getStrict());
        dataSource.setStrategy(properties.getStrategy());
        dataSource.setProvider(dynamicDataSourceProvider);
        dataSource.setP6spy(properties.getP6spy());
        dataSource.setSeata(properties.getSeata());
        return dataSource;
    }
}

4、使用@DS切换数据源,默认使用master

在这里插入图片描述

四、拓展:相关文章推荐

sharding-jdbc 分库分表的 4种分片策略
shardingsphere+dynamic+mybatisPlugs配置多数据源

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值