一、先看下简单的库、表结构
ORM框架自动生成的代码,太简单就不上代码了,主要是理解思路
二、引入依赖
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.1.1</version>
</dependency>
server.port=8085
# 数据源 ds1,ds2,ds3,ds4
spring.shardingsphere.datasource.names=ds1,ds2,ds3,ds4
# 避免实体类绑定多个数据源报错
spring.main.allow-bean-definition-overriding=true
# 第一个数据库
spring.shardingsphere.datasource.ds1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds1.jdbc-url=jdbc:mysql://8.142.19.202:3306/st-test1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
spring.shardingsphere.datasource.ds1.username=root
spring.shardingsphere.datasource.ds1.password=你的密码
# 第二个数据库
spring.shardingsphere.datasource.ds2.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds2.jdbc-url=jdbc:mysql://8.142.19.202:3306/st-test2?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
spring.shardingsphere.datasource.ds2.username=root
spring.shardingsphere.datasource.ds2.password=你的密码
# 第三个数据库
spring.shardingsphere.datasource.ds3.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds3.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds3.jdbc-url=jdbc:mysql://8.142.19.202:3306/st-test3?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
spring.shardingsphere.datasource.ds3.username=root
spring.shardingsphere.datasource.ds3.password=你的密码
# 第四个数据库
spring.shardingsphere.datasource.ds4.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds4.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds4.jdbc-url=jdbc:mysql://8.142.19.202:3306/st-test4?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
spring.shardingsphere.datasource.ds4.username=root
spring.shardingsphere.datasource.ds4.password=你的密码
#配置分库规则
spring.shardingsphere.sharding.tables.tb_user.database-strategy.inline.sharding-column=id
spring.shardingsphere.sharding.tables.tb_user.database-strategy.inline.algorithm-expression=ds$->{id % 4 + 1}
# 指定st_user表的数据分布情况,配置数据节点,行表达式标识符使用 ${...} 或 $->{...},
# 但前者与 Spring 本身的文件占位符冲突,所以在 Spring 环境中建议使用 $->{...}
spring.shardingsphere.sharding.tables.tb_user.actual-data-nodes=ds$->{1..4}.tb_user$->{1..4}
# 指定st_user表的分片策略,分片策略包括【分片键和分片算法】`
spring.shardingsphere.sharding.tables.tb_user.table-strategy.inline.sharding-column=id
spring.shardingsphere.sharding.tables.tb_user.table-strategy.inline.algorithm-expression=tb_user$->{id % 4 + 1}
引出两个问题
一)最新版本4.1.1与你的Spring版本兼容性有问题,使用下面这个版本即可
<dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-boot-starter</artifactId> <version>4.0.0-RC1</version> </dependency>
二)dataSource这个bean无法注册
spring.main.allow-bean-definition-overriding=true
三、简单配置结束,上代码测试
package com.example.test05.demo.controller;
import com.example.test05.demo.mapper.TbUserMapper;
import com.example.test05.demo.model.TbUserDO;
import com.example.test05.demo.service.TbUserService;
import com.example.test05.demo.tool.JsonData;
import jdk.nashorn.internal.objects.annotations.Getter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* <p>
* 前端控制器
* </p>
*
* @author DBC
* @since 2021-11-05
*/
@RestController
@RequestMapping("/tbUserDO")
public class TbUserController {
@Autowired
private TbUserService tbUserService;
@Autowired
private TbUserMapper tbUserMapper;
@PostMapping()
public JsonData install() {
for (int i = 0; i < 10; i++) {
TbUserDO tbUserDO = new TbUserDO();
tbUserDO.setId((long) i);
tbUserDO.setName("大猪头" + i);
tbUserDO.setAge("" + i);
tbUserMapper.insert(tbUserDO);
}
return JsonData.buildSuccess();
}
@GetMapping()
public JsonData chaxun() {
List<TbUserDO> tbUserDOList = tbUserService.list();
System.out.println(tbUserDOList.size());
return JsonData.buildSuccess(tbUserDOList);
}
@DeleteMapping()
public JsonData shanchu() {
tbUserService.removeById(1);
return JsonData.buildSuccess();
}
@PutMapping()
public JsonData xiugai() {
TbUserDO tbUserDO = new TbUserDO();
tbUserDO.setId((long) 2);
tbUserDO.setName("大猪头666");
tbUserDO.setAge("");
tbUserMapper.updateById(tbUserDO);
return JsonData.buildSuccess();
}
}
进阶操作——广播表
建对应的表、简单的ORM操作
在配置文件追加广播表
#配置广播表 spring.shardingsphere.sharding.broadcast-tables=tb_type
测试一下
@PostMapping("installType")
public JsonData installType() {
TbType tbType = new TbType();
tbType.setType("大猪头");
tbTypeMapper.insert(tbType);
return JsonData.buildSuccess();
} 进阶操作——绑定表
- 什么是绑定表
- 指分片规则一致的主表和子表
- 绑定表之间的多表关联查询不会出现笛卡尔积关联,关联查询效率将大大提升
先看数据库
画一张图辅助理解
配置对应的分表策略
#配置分库规则
spring.shardingsphere.sharding.tables.tb_user.database-strategy.inline.sharding-column=id
spring.shardingsphere.sharding.tables.tb_user.database-strategy.inline.algorithm-expression=ds$->{id % 4 + 1}
spring.shardingsphere.sharding.tables.tb_user_item.database-strategy.inline.sharding-column=id
spring.shardingsphere.sharding.tables.tb_user_item.database-strategy.inline.algorithm-expression=ds$->{id % 4 + 1}
# 指定st_user表的数据分布情况,配置数据节点,行表达式标识符使用 ${...} 或 $->{...},
# 但前者与 Spring 本身的文件占位符冲突,所以在 Spring 环境中建议使用 $->{...}
# 指定st_user表的分片策略,分片策略包括【分片键和分片算法】`
spring.shardingsphere.sharding.tables.tb_user.actual-data-nodes=ds$->{1..4}.tb_user$->{1..4}
spring.shardingsphere.sharding.tables.tb_user.table-strategy.inline.sharding-column=dev_id
spring.shardingsphere.sharding.tables.tb_user.table-strategy.inline.algorithm-expression=tb_user$->{dev_id % 4 + 1}
# 指定st_user_item表的分片策略,分片策略包括【分片键和分片算法】`
spring.shardingsphere.sharding.tables.tb_user_item.actual-data-nodes=ds$->{1..4}.tb_user_item$->{1..4}
spring.shardingsphere.sharding.tables.tb_user_item.table-strategy.inline.sharding-column=dev_id
spring.shardingsphere.sharding.tables.tb_user_item.table-strategy.inline.algorithm-expression=tb_user_item$->{dev_id % 4 + 1}
#配置广播表
spring.shardingsphere.sharding.broadcast-tables=tb_type
#配置绑定表
spring.shardingsphere.sharding.binding-tables[0] = tb_user,tb_user_item 我们来看看效果
进阶操作——多种分片策略实战
为了能够有更加自定义的分库分表操作,我们需要在java配置一些我们需要的分库分表策略
#精准分片-水平分表
# 指定product_order表的数据分布情况,配置数据节点,在 Spring 环境中建议使用 $->{...}
spring.shardingsphere.sharding.tables.tb_user.actual-data-nodes=ds$->{1..4}.tb_user$->{1..4}
#指定精准分片算法(水平分库) 根据id分库
spring.shardingsphere.sharding.tables.tb_user.database-strategy.standard.sharding-column=id
spring.shardingsphere.sharding.tables.tb_user.database-strategy.standard.precise-algorithm-class-name=com.example.test05.demo.config.CustomDBPreciseShardingAlgorithm
#指定精准分片算法(水平分表)
spring.shardingsphere.sharding.tables.tb_user.table-strategy.standard.sharding-column=dev_id
spring.shardingsphere.sharding.tables.tb_user.table-strategy.standard.precise-algorithm-class-name=com.example.test05.demo.config.CustomTablePreciseShardingAlgorithm
#范围分片(水平分表)
spring.shardingsphere.sharding.tables.tb_user.table-strategy.standard.range-algorithm-class-name=com.example.test05.demo.config.CustomRangeShardingAlgorithm 分库配置
CustomDBPreciseShardingAlgorithm
package com.example.test05.demo.config;
/**
* @author DBC
* @date 2022/7/13 14:52
* @network dbc655.top
*/
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
import java.util.Collection;
public class CustomDBPreciseShardingAlgorithm implements PreciseShardingAlgorithm<Long> {
/**
* @param dataSourceNames 数据源集合
* 在分库时值为所有分片库的集合 databaseNames
* 分表时为对应分片库中所有分片表的集合 tablesNames
* @param preciseShardingValue 分片属性,包括
* logicTableName 为逻辑表,
* columnName 分片健(字段),
* value 为从 SQL 中解析出的分片健的值
* @return
*/
@Override
public String doSharding(Collection<String> dataSourceNames, PreciseShardingValue<Long> preciseShardingValue) {
for (String datasourceName : dataSourceNames) {
String value = (preciseShardingValue.getValue() % dataSourceNames.size() + 1) + "";
//ds0、ds1
if (datasourceName.endsWith(value)) {
return datasourceName;
}
}
return null;
}
} CustomTablePreciseShardingAlgorithm
package com.example.test05.demo.config;
/**
* @author DBC
* @date 2022/7/13 14:51
* @network dbc655.top
*/
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
import java.util.Collection;
public class CustomTablePreciseShardingAlgorithm implements PreciseShardingAlgorithm
/**
* @param dataSourceNames 数据源集合
* 在分库时值为所有分片库的集合 databaseNames
* 分表时为对应分片库中所有分片表的集合 tablesNames
* @param preciseShardingValue 分片属性,包括
* logicTableName 为逻辑表,
* columnName 分片健(字段),
* value 为从 SQL 中解析出的分片健的值
* @return
*/
@Override
public String doSharding(Collection
for (String datasourceName : dataSourceNames) {
String value = (preciseShardingValue.getValue() % dataSourceNames.size() + 1) + "";
//product_order_0
if (datasourceName.endsWith(value)) {
return datasourceName;
}
}
return null;
}
}
between有些版本会报错,就算不报错,也会发生恐怖的笛卡尔积!我们需要配置一下CustomRangeShardingAlgorithm
package com.example.test05.demo.config;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingValue;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;
/**
* @author DBC
* @date 2022/7/13 14:34
* @network dbc655.top
*/
public class CustomRangeShardingAlgorithm implements RangeShardingAlgorithm<Long> {
/**
* @param dataSourceNames 数据源集合
* 在分库时值为所有分片库的集合 databaseNames
* 分表时为对应分片库中所有分片表的集合 tablesNames
* @param shardingValue 分片属性,包括
* logicTableName 为逻辑表,
* columnName 分片健(字段),
* value 为从 SQL 中解析出的分片健的值
* @return
*/
@Override
public Collection<String> doSharding(Collection<String> dataSourceNames, RangeShardingValue<Long> shardingValue) {
Set<String> result = new LinkedHashSet<>();
//between 开始值
Long lower = shardingValue.getValueRange().lowerEndpoint();
//between 结束值
Long upper = shardingValue.getValueRange().upperEndpoint();
for (long i = lower; i <= upper; i++) {
for (String datasource : dataSourceNames) {
String value = (i % dataSourceNames.size() + 1) + "";
if (datasource.endsWith(value)) {
result.add(datasource);
}
}
}
return result;
}
} 大功告成!撒花[aru_50]
本文作者为DBC,转载请注明。






