您好,登录后才能下订单哦!
# 如何使用分库分表Sharding-JDBC
## 目录
- [一、分库分表核心概念](#一分库分表核心概念)
- [1.1 什么是分库分表](#11-什么是分库分表)
- [1.2 垂直拆分与水平拆分](#12-垂直拆分与水平拆分)
- [1.3 分库分表适用场景](#13-分库分表适用场景)
- [二、Sharding-JDBC架构解析](#二sharding-jdbc架构解析)
- [2.1 核心组件与工作原理](#21-核心组件与工作原理)
- [2.2 与MyCat对比](#22-与mycat对比)
- [2.3 版本演进与新特性](#23-版本演进与新特性)
- [三、基础环境搭建](#三基础环境搭建)
- [3.1 依赖配置](#31-依赖配置)
- [3.2 数据源配置](#32-数据源配置)
- [3.3 分片规则配置](#33-分片规则配置)
- [四、分片策略详解](#四分片策略详解)
- [4.1 标准分片策略](#41-标准分片策略)
- [4.2 复合分片策略](#42-复合分片策略)
- [4.3 Hint分片策略](#43-hint分片策略)
- [4.4 不分片策略](#44-不分片策略)
- [五、分布式事务实现](#五分布式事务实现)
- [5.1 XA事务](#51-xa事务)
- [5.2 Seata柔性事务](#52-seata柔性事务)
- [5.3 BASE事务](#53-base事务)
- [六、实战案例](#六实战案例)
- [6.1 电商订单分库分表](#61-电商订单分库分表)
- [6.2 多租户SAAS系统](#62-多租户saas系统)
- [6.3 物联网时序数据](#63-物联网时序数据)
- [七、性能优化](#七性能优化)
- [7.1 路由优化](#71-路由优化)
- [7.2 合并执行优化](#72-合并执行优化)
- [7.3 连接池配置](#73-连接池配置)
- [八、运维监控](#八运维监控)
- [8.1 指标监控集成](#81-指标监控集成)
- [8.2 链路追踪](#82-链路追踪)
- [8.3 慢查询分析](#83-慢查询分析)
- [九、常见问题解决方案](#九常见问题解决方案)
- [9.1 分布式ID生成](#91-分布式id生成)
- [9.2 跨库JOIN处理](#92-跨库join处理)
- [9.3 分布式序列问题](#93-分布式序列问题)
- [十、未来发展趋势](#十未来发展趋势)
- [10.1 云原生支持](#101-云原生支持)
- [10.2 多模异构支持](#102-多模异构支持)
- [10.3 智能化方向](#103-智能化方向)
## 一、分库分表核心概念
### 1.1 什么是分库分表
分库分表是数据库水平扩展的核心技术手段,主要解决单机数据库在数据量增长时出现的性能瓶颈问题。当单表数据量超过500万行或数据库实例QPS超过3000时,就应该考虑分库分表方案。
**技术本质**:通过数据分片(Sharding)将数据集分散到不同的物理节点,使每个节点只处理部分数据,从而提升整体系统的处理能力。
### 1.2 垂直拆分与水平拆分
#### 垂直拆分(Vertical Partitioning)
```sql
-- 原始用户表
CREATE TABLE user (
id BIGINT,
username VARCHAR(50),
password VARCHAR(100),
profile_json TEXT,
login_log TEXT
);
-- 拆分后
CREATE TABLE user_basic (
id BIGINT,
username VARCHAR(50),
password VARCHAR(100)
);
CREATE TABLE user_profile (
user_id BIGINT,
profile_json TEXT
);
// 按用户ID范围分片
shardingRuleConfig.getTableRuleConfigs().add(
TableRuleConfiguration.builder("t_order")
.actualDataNodes("ds${0..1}.t_order_${0..15}")
.databaseShardingStrategy(
new StandardShardingStrategyConfiguration("user_id", "dbShardingAlgorithm"))
.tableShardingStrategy(
new StandardShardingStrategyConfiguration("order_id", "tableShardingAlgorithm"))
.build());
场景类型 | 典型特征 | 解决方案 |
---|---|---|
高并发读写 | QPS > 5000 | 分库分散压力 |
大数据量存储 | 单表 > 500万行 | 分表存储 |
地理分布式访问 | 跨地域访问延迟高 | 按地域分库 |
多租户系统 | 租户数据隔离需求 | 按租户ID分库 |
graph TD
A[应用代码] --> B[Sharding-JDBC Driver]
B --> C[SQL解析引擎]
C --> D[路由引擎]
D --> E[改写引擎]
E --> F[执行引擎]
F --> G[结果归并]
G --> H[返回结果]
关键组件说明: 1. SQL解析:基于Apache Calcite实现SQL语法树解析 2. 路由引擎:支持精确路由、范围路由、广播路由等多种模式 3. 执行引擎:自动建立多线程执行管道 4. 归并引擎:支持流式归并、内存归并等多种方式
特性 | Sharding-JDBC | MyCat |
---|---|---|
架构模式 | 客户端直连 | 代理层 |
性能损耗 | % | 15%-20% |
功能完整性 | 分片+分布式事务 | 分片+集群管理 |
运维复杂度 | 低(无中间件) | 高(需维护代理) |
版本迭代 | 活跃(Apache维护) | 社区维护 |
5.x版本重大改进: 1. 可插拔架构:支持SPI扩展 2. 分布式事务:XA/SAGA/SEATA全支持 3. 数据加密:列级别透明加密 4. 影子库压测:全链路压测支持
Maven核心依赖:
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core</artifactId>
<version>5.3.2</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>4.0.3</version>
</dependency>
Spring Boot自动配置:
spring.shardingsphere.datasource.names=ds0,ds1
spring.shardingsphere.datasource.ds0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds0.jdbc-url=jdbc:mysql://localhost:3306/ds0
spring.shardingsphere.datasource.ds0.username=root
spring.shardingsphere.datasource.ds0.password=123456
YAML格式配置示例:
spring:
shardingsphere:
datasource:
names: ds0,ds1
ds0:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/ds0
username: root
password: 123456
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
maximum-pool-size: 20
Java API配置方式:
// 分片算法配置
Properties dbShardingProps = new Properties();
dbShardingProps.setProperty("algorithm-expression", "ds${user_id % 2}");
ShardingSphereAlgorithmConfiguration dbShardingAlgorithm =
new ShardingSphereAlgorithmConfiguration("INLINE", dbShardingProps);
// 表规则配置
ShardingTableRuleConfiguration orderTableRule = new ShardingTableRuleConfiguration(
"t_order", "ds${0..1}.t_order_${0..15}");
orderTableRule.setDatabaseShardingStrategy(
new StandardShardingStrategyConfiguration("user_id", "dbShardingAlgorithm"));
orderTableRule.setTableShardingStrategy(
new StandardShardingStrategyConfiguration("order_id", "tableShardingAlgorithm"));
精确分片算法实现:
public class OrderDatabaseShardingAlgorithm implements PreciseShardingAlgorithm<Long> {
@Override
public String doSharding(Collection<String> availableTargetNames,
PreciseShardingValue<Long> shardingValue) {
for (String each : availableTargetNames) {
if (each.endsWith(shardingValue.getValue() % 2 + "")) {
return each;
}
}
throw new IllegalArgumentException();
}
}
范围分片算法示例:
public class OrderRangeShardingAlgorithm implements RangeShardingAlgorithm<Long> {
@Override
public Collection<String> doSharding(Collection<String> availableTargetNames,
RangeShardingValue<Long> shardingValue) {
Set<String> result = new LinkedHashSet<>();
Long lower = shardingValue.getValueRange().lowerEndpoint();
Long upper = shardingValue.getValueRange().upperEndpoint();
for (long i = lower; i <= upper; i++) {
for (String each : availableTargetNames) {
if (each.endsWith(i % 2 + "")) {
result.add(each);
}
}
}
return result;
}
}
多字段分片配置:
spring:
shardingsphere:
sharding:
tables:
t_order:
actual-data-nodes: ds$->{0..1}.t_order_$->{0..15}
database-strategy:
complex:
sharding-columns: user_id,order_date
algorithm-class-name: com.example.ComplexShardingAlgorithm
复合算法实现:
public class ComplexShardingAlgorithm implements ComplexKeysShardingAlgorithm<Comparable<?>> {
@Override
public Collection<String> doSharding(Collection<String> availableTargetNames,
ComplexKeysShardingValue<Comparable<?>> shardingValue) {
Map<String, Collection<Comparable<?>>> columnValues = shardingValue.getColumnNameAndShardingValuesMap();
Collection<Comparable<?>> userIds = columnValues.get("user_id");
Collection<Comparable<?>> orderDates = columnValues.get("order_date");
Set<String> result = new HashSet<>();
// 实现自定义复合分片逻辑
for (Comparable<?> userId : userIds) {
for (Comparable<?> orderDate : orderDates) {
int dbSuffix = (userId.hashCode() & Integer.MAX_VALUE) % 2;
int tableSuffix = orderDate.hashCode() % 16;
result.add(String.format("ds%d.t_order_%d", dbSuffix, tableSuffix));
}
}
return result;
}
}
强制路由配置:
// 设置分片值
HintManager.getInstance().setDatabaseShardingValue(1);
try {
// 执行SQL(将强制路由到ds1)
orderRepository.selectAll();
} finally {
HintManager.clear();
}
Hint算法实现:
public class OrderHintShardingAlgorithm implements HintShardingAlgorithm<Integer> {
@Override
public Collection<String> doSharding(Collection<String> availableTargetNames,
HintShardingValue<Integer> shardingValue) {
Collection<String> result = new ArrayList<>();
for (String each : availableTargetNames) {
for (Integer value : shardingValue.getValues()) {
if (each.endsWith(value.toString())) {
result.add(each);
}
}
}
return result;
}
}
广播表配置:
spring:
shardingsphere:
sharding:
broadcast-tables: t_config
绑定表配置:
spring:
shardingsphere:
sharding:
binding-tables:
- t_order,t_order_item
配置XA事务管理器:
spring:
shardingsphere:
props:
xa-transaction-manager-type: Atomikos
事务使用示例:
@ShardingSphereTransactionType(TransactionType.XA)
@Transactional
public void placeOrder(Order order) {
// 业务逻辑
}
Seata集成配置:
spring:
shardingsphere:
props:
seata:
tx-service-group: my_test_tx_group
AT模式示例:
@ShardingSphereTransactionType(TransactionType.BASE)
@Transactional
public void updateOrder(Order order) {
// 第一阶段:执行业务SQL并生成undo log
orderMapper.update(order);
// 第二阶段:由Seata自动提交/回滚
}
Saga模式配置:
@ShardingSphereTransactionType(TransactionType.SAGA)
@SagaStart(timeoutSeconds = 300)
public void createOrder(Order order) {
// 正向操作
orderService.create(order);
inventoryService.reduce(order.getItemId(), order.getCount());
// 补偿操作定义
@Compensate
public void compensateCreate(Order order) {
orderService.delete(order.getId());
inventoryService.increase(order.getItemId(), order.getCount());
}
}
场景特点: - 订单量日均10万+ - 需要按用户维度查询 - 历史订单需要归档
分片方案:
spring:
shardingsphere:
sharding:
tables:
t_order:
actual-data-nodes: ds$->{0..3}.t_order_$->{0..15}
database-strategy:
inline:
sharding-column: user_id
algorithm-expression: ds$->{user_id % 4}
table-strategy:
standard:
sharding-column: order_time
precise-algorithm-class-name: com.example.OrderTimePreciseShardingAlgorithm
range-algorithm-class-name: com.example.OrderTimeRangeShardingAlgorithm
场景特点: - 租户数量超过1000+ - 需要严格数据隔离 - 支持自定义租户分片策略
解决方案:
public class TenantShardingAlgorithm implements PreciseShardingAlgorithm<String> {
@Override
public String doSharding(Collection<String> availableTargetNames,
PreciseShardingValue<String> shardingValue) {
// 根据租户ID哈希分片
int hash = Math.abs(shardingValue.getValue().hashCode());
int index = hash % availableTargetNames.size();
return new ArrayList<>(availableTargetNames).get(index);
}
}
特殊需求: - 时间序列数据 - 需要定期自动创建新表 - 支持冷热数据分离
动态分片方案:
public class TimeSeriesShardingAlgorithm implements PreciseShardingAlgorithm<Date> {
private static final DateTimeFormatter TABLE_FORMAT =
DateTimeFormatter.ofPattern("yyyy_MM");
@Override
public String doSharding(Collection<String> availableTargetNames,
PreciseShardingValue<Date> shardingValue) {
LocalDate date = shardingValue.getValue().toInstant()
.atZone(ZoneId.systemDefault()).toLocalDate();
String tableSuffix = date.format(TABLE_FORMAT);
return availableTargetNames.stream()
.filter(each -> each.endsWith(tableSuffix))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("No table for date " + date));
}
}
最佳实践: 1. 避免全库全表扫描:
-- 错误写法(导致广播路由)
SELECT * FROM t_order WHERE status = 1;
-- 正确写法(带上分片键)
SELECT * FROM t_order WHERE user_id = 123 AND status = 1;
-- 分片键必须包含在索引中
ALTER TABLE t_order ADD INDEX idx_user_status (user_id, status);
配置参数调优:
spring:
shardingsphere:
props:
max.connections.size.per.query: 5 # 每个查询最大连接数
executor.size: 20 # 执行线程池大小
kernel.executor.size: 20 # 内核线程池大小
HikariCP优化建议: “`yaml spring: shardingsphere: datasource: ds0: hikari: maximum-pool-size:
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。