一、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配置多数据源