分片键(Sharding Key)的选择直接决定了分片策略的效果。一个优秀的分片键需要满足以下特性:
1. 数据分布均匀性
• 基数要足够大,避免数据倾斜
• 增长趋势可预测,便于容量规划
• 避免热点,如使用时间戳作为分片键时要注意追加写入问题
2. 查询模式适配性
• 与业务最频繁的查询模式匹配
• 支持就近路由,提升查询效率
• 考虑批量操作场景的性能影响
实践要点:
-- 不推荐:使用自增ID作为分片键 CREATE TABLE orders ( id BIGINT PRIMARY KEY, -- 易造成写入热点 user_id BIGINT, order_time TIMESTAMP ); -- 推荐:使用user_id作为分片键 CREATE TABLE orders ( id BIGINT, user_id BIGINT, -- 分片键 order_time TIMESTAMP, PRIMARY KEY (user_id, id) );
案例1:电商订单分片 - 场景:大型电商平台日订单量千万级 - 挑战:历史订单查询与实时订单写入并存 - 解决方案:采用用户ID+时间范围的复合分片策略 订单表分片设计: CREATE TABLE orders_${user_id % 256}_${yyyyMM} ( id BIGINT, user_id BIGINT, order_time TIMESTAMP, status VARCHAR(32), PRIMARY KEY (user_id, id) ) PARTITION BY RANGE (order_time);
跨分片事务是分片系统的技术难点,需要在一致性和性能之间做出权衡。
• 实现两阶段提交(2PC)协议
• 使用三阶段提交(3PC)提高可用性
• 采用SAGA模式处理长事务
@Transactional public void transferMoney(long userId1, long userId2, BigDecimal amount) { // 重要:先对分片键排序,避免死锁 long firstId = Math.min(userId1, userId2); long secondId = Math.max(userId1, userId2); Account account1 = accountDao.lockAccount(firstId); Account account2 = accountDao.lockAccount(secondId); // 执行转账逻辑 account1.deduct(amount); account2.add(amount); }
注意事项:
• 避免大规模跨分片事务:可能导致性能急剧下降
• 合理设计分片策略:将相关联的数据放在同一分片
• 使用补偿机制:处理分布式事务失败场景
• 吞吐量基准:单分片写入QPS > 5000
• 跨分片查询延迟:P99 < 200ms
• 关键监控指标:
a.分片数据分布偏差率 < 15%
b.跨分片事务比例 < 5%
c.单分片存储容量利用率 < 75%
准备新节点预热数据调整路由表数据同步切换流量清理旧数据
• 双写方案:新写入同时写入新旧节点
• 快照+增量:先迁移基础数据,再同步增量
• 虚拟节点:使用一致性哈希实现平滑扩容
核心代码示例:
public class ConsistentHash<T> { private final int numberOfReplicas; // 虚拟节点数 private final SortedMap<Integer, T> circle = new TreeMap<>(); public void addNode(T node) { for (int i = 0; i < numberOfReplicas; i++) { circle.put(hash(node.toString() + i), node); } } public T getNode(Object key) { if (circle.isEmpty()) { return null; } int hash = hash(key); if (!circle.containsKey(hash)) { SortedMap<Integer, T> tailMap = circle.tailMap(hash); hash = tailMap.isEmpty() ? circle.firstKey() : tailMap.firstKey(); } return circle.get(hash); } }
数据倾斜 性能下降 节点故障 发现分片异常判断类型重平衡策略分析慢查询故障转移执行修复
常见故障处理流程:
1. 数据倾斜
• 触发条件:单分片负载超过平均值150%
• 处理方案:动态分片+数据重平衡
• 预防措施:实时监控分片数据分布
2. 热点分片
• 问题表现:特定分片QPS突增
• 解决方案:引入二级分片+本地缓存
• 代码示例:
@Cacheable(key = "#userId", condition = "#userId % 256 == hotShardId") public UserOrder getOrder(long userId) { // 热点分片走二级缓存 if (isHotShard(userId)) { return localCache.get(userId); } return orderMapper.getOrder(userId); }
1. 多维度分片支持
public interface ShardingStrategy { String getShardingKey(Object params); // 支持自定义分片算法 int calculateShard(String shardingKey); // 支持分片规则动态变更 void updateShardingRule(ShardingRule rule); }
2. 分片管理面板
• 分片健康度可视化
• 自动化运维能力
• 分片扩缩容向导
场景 | 推荐方案 | 特点 |
单元化部署 | ShardingSphere | 异构数据源整合能力强 |
海量数据 | TiDB | 强一致性,自动分片 |
全球化部署 | CockroachDB | 跨区域一致性好 |