Java 面试题:你们公司的数据库有分库分表吗?如何实现的?
一、分库分表触发条件
关键指标参考:
- 单表数据量:500万行(机械硬盘)/ 2000万行(SSD)
- 磁盘空间:单库超过2TB
- 连接数瓶颈:MySQL连接数超过2000
二、分片策略设计
1. 水平分片方案对比
分片方式 | 实现方法 | 优点 | 缺点 |
哈希取模 | user_id % 64 | 数据分布均匀 | 扩容需要rehash |
范围分片 | create_time < '2023' | 易范围查询 | 可能产生热点 |
一致性哈希 | 虚拟节点环 | 扩容影响小 | 实现复杂 |
基因分片 | 分片键包含业务ID | 避免跨分片查询 | 设计复杂度高 |
2. 分片键选择原则
- 高频查询字段:如用户ID、订单号
- 业务连续性:时间字段(create_time)
- 数据均匀性:避免性别等低区分度字段
基因分片示例:
// 用户ID基因分片(后4位含分片信息)
Long userId = 2023081912345678L;
int shardKey = (userId % 10000) / 100; // 取倒数第5-6位
三、技术架构实现
1. 中间件选型对比
中间件 | 接入方式 | 事务支持 | 运维复杂度 |
ShardingSphere | 代码/配置双模式 | XA/Seata | ★★☆ |
MyCat | 代理层 | 弱事务支持 | ★★★ |
Vitess | 协议层 | 分布式事务 | ★★★★ |
2. 推荐架构方案
# ShardingSphere配置
rules:
- !SHARDING
tables:
orders:
actualDataNodes: ds_${0..3}.orders_${0..7}
tableStrategy:
standard:
shardingColumn: order_id
shardingAlgorithmName: mod_hash
keyGenerateStrategy:
column: order_id
keyGeneratorName: snowflake
shardingAlgorithms:
mod_hash:
type: HASH_MOD
props:
sharding-count: 32
四、数据迁移方案
1. 双写迁移流程
2. 灰度切换步骤:
- 阶段一:10%流量切新库,校验数据一致性
- 阶段二:50%流量,观察慢查询率(<5%)
- 阶段三:全量切换,旧库保留7天回滚窗口
数据校验工具:
pt-table-checksum \
--databases=test \
--tables=orders \
--replicate=test.checksums \
--no-check-binlog-format
五、典型问题解决方案
1. 跨分片查询
- 全局二级索引:ES同步关键字段
- 广播表:存储基础数据(如省份编码)
- 联邦查询:通过ShardingSphere的Federation执行引擎
2. 分布式事务
- Seata AT模式:
@GlobalTransactional
public void createOrder() {
orderService.insert();
inventoryService.deduct();
}
- 最大努力通知:异步消息+本地事务表
3. 分页排序优化
/* 改写前 */
SELECT * FROM orders
WHERE user_id=123
ORDER BY create_time DESC
LIMIT 10000,10;
/* 改写后 */
SELECT * FROM orders
WHERE user_id=123 AND create_time < '2023-08-01'
ORDER BY create_time DESC
LIMIT 10;
六、监控指标设计
关键Dashboard指标:
- 分片负载均衡度:标准差 ≤15%
- 跨分片查询率:<5%(通过SQL审计日志统计)
- XA事务成功率:≥99.9%
- 扩容水位预警:单分片数据量 ≥80%阈值
报警规则示例:
- alert: ShardingHotspot
expr: max(shard_disk_usage) > 85%
for: 10m
labels:
severity: critical
annotations:
summary: "分片 {{ $labels.shard }} 磁盘使用超过85%"
总结建议
- 分库分表时机:数据量达到单机瓶颈的70%时启动
- 分片数量公式:预估3年数据量 / 单分片承载能力 × 2(冗余)
- 技术选型优先级:ShardingSphere > MyCat > 自研中间件
通过上述方案,我们成功支撑了日均10亿级订单的交易系统,分片扩容操作可在1小时内完成,跨分片查询响应时间控制在200ms以内。实际应用中需根据业务特性灵活调整分片策略,并建立完善的监控应急体系。