数据库与缓存--分库分表实战指南

张开发
2026/4/11 10:11:35 15 分钟阅读

分享文章

数据库与缓存--分库分表实战指南
系列导读本篇将深入讲解分库分表的核心原理、设计策略与最佳实践。文章目录一、分库分表概述1.1 为什么需要分库分表1.2 分库 vs 分表1.3 架构图二、分片策略2.1 分片键选择2.2 分片算法2.3 分片配置三、主键设计3.1 主键问题3.2 雪花算法四、中间件选型4.1 中间件对比4.2 ShardingSphere 优势五、实战案例5.1 订单分库分表5.2 跨库查询总结一、分库分表概述1.1 为什么需要分库分表问题说明数据量过大单表超过千万级查询变慢并发量过大单库连接数有限单点故障单库宕机影响全局1.2 分库 vs 分表方式说明解决问题垂直分库按业务拆分数据库业务解耦、独立扩展垂直分表按字段拆分表减少IO、提高性能水平分库按数据拆分到多个库解决高并发、大数据量水平分表按数据拆分到多个表解决单表数据量过大1.3 架构图垂直分库 ┌─────────┐ ┌─────────┐ ┌─────────┐ │ 用户库 │ │ 订单库 │ │ 商品库 │ └─────────┘ └─────────┘ └─────────┘ 水平分库 ┌─────────┐ ┌─────────┐ ┌─────────┐ │ 订单库0 │ │ 订单库1 │ │ 订单库2 │ │ order_0 │ │ order_1 │ │ order_2 │ │ order_1 │ │ order_2 │ │ order_0 │ └─────────┘ └─────────┘ └─────────┘二、分片策略2.1 分片键选择分片键选择原则 1. 数据分布均匀 2. 查询命中率高 3. 业务关联性强 常见分片键 - 用户ID用户相关业务 - 订单ID订单相关业务 - 时间日志、流水类业务2.2 分片算法算法说明优点缺点Hashhash(key) % N分布均匀扩容困难Range按范围划分扩容简单热点问题一致性Hash环形Hash扩容影响小实现复杂取模key % N简单扩容困难2.3 分片配置# ShardingSphere 配置spring:shardingsphere:rules:sharding:tables:t_order:actual-data-nodes:ds0.t_order_$-{0..1}table-strategy:standard:sharding-column:order_idsharding-algorithm-name:order-inlinekey-generate-strategy:column:order_idkey-generator-name:snowflakesharding-algorithms:order-inline:type:INLINEprops:algorithm-expression:t_order_$-{order_id % 2}key-generators:snowflake:type:SNOWFLAKE三、主键设计3.1 主键问题单库自增ID问题 - 分库后ID冲突 - 无法保证全局唯一 解决方案 - UUID无序、太长 - 雪花算法推荐 - 号段模式数据库批量获取3.2 雪花算法// 雪花算法生成分布式IDpublicclassSnowflakeIdWorker{privatefinallongworkerId;privatefinallongdatacenterId;privatelongsequence0L;privatelonglastTimestamp-1L;publicsynchronizedlongnextId(){longtimestampSystem.currentTimeMillis();if(timestamplastTimestamp){thrownewRuntimeException(时钟回拨);}if(lastTimestamptimestamp){sequence(sequence1)4095;if(sequence0){timestamptilNextMillis(lastTimestamp);}}else{sequence0L;}lastTimestamptimestamp;return((timestamp-1288834974657L)22)|(datacenterId17)|(workerId12)|sequence;}}四、中间件选型4.1 中间件对比中间件类型优点缺点ShardingSphere客户端轻量、功能全侵入应用MyCat服务端对应用透明性能有损耗Vitess服务端大厂背书学习成本高4.2 ShardingSphere 优势✅ 功能丰富分片、读写分离、加密、影子库 ✅ 生态完善支持 Spring Boot、Namespace ✅ 性能优秀客户端直连数据库 ✅ 社区活跃Apache 顶级项目五、实战案例5.1 订单分库分表// 订单实体DataTableName(t_order)publicclassOrder{TableId(typeIdType.ASSIGN_ID)// 雪花算法privateLongorderId;privateLonguserId;privateStringorderNo;privateBigDecimalamount;privateIntegerstatus;privateLocalDateTimecreateTime;}// 分片配置ConfigurationpublicclassShardingConfig{BeanpublicDataSourcedataSource()throwsSQLException{// 数据源配置MapString,DataSourcedataSourceMapnewHashMap();dataSourceMap.put(ds0,createDataSource(192.168.1.100:3306/order_db0));dataSourceMap.put(ds1,createDataSource(192.168.1.101:3306/order_db1));// 分片规则ShardingRuleConfigurationshardingRuleConfignewShardingRuleConfiguration();shardingRuleConfig.getTables().add(getOrderTableRuleConfiguration());returnShardingDataSourceFactory.createDataSource(dataSourceMap,shardingRuleConfig,newProperties());}privateShardingTableRuleConfigurationgetOrderTableRuleConfiguration(){ShardingTableRuleConfigurationresultnewShardingTableRuleConfiguration(t_order,ds${0..1}.t_order_${0..1});result.setTableShardingStrategy(newStandardShardingStrategyConfiguration(order_id,t_order_inline));returnresult;}}5.2 跨库查询// 跨库查询问题解决方案ServicepublicclassOrderQueryService{// 方案1绑定表关联分片键publicListOrderqueryByUserId(LonguserId){returnorderMapper.selectByUserId(userId);}// 方案2冗余数据publicListOrderqueryByOrderNo(StringorderNo){// 从冗余表查询returnorderIndexMapper.selectByOrderNo(orderNo);}// 方案3广播表publicOrderqueryWithRegion(LongorderId){OrderorderorderMapper.selectById(orderId);// 区域信息从广播表获取RegionregionregionMapper.selectById(order.getRegionId());order.setRegionName(region.getName());returnorder;}}总结✅分库分表概述为什么需要、分库vs分表✅分片策略分片键、分片算法✅主键设计雪花算法✅中间件选型ShardingSphere、MyCat✅实战案例订单分库分表下篇预告Redis 集群架构与优化作者刘~浪地球系列数据库与缓存二更新时间2026-04-11

更多文章