核心内容摘要
亚洲美女-造相Z-Turbo零基础教程:5分钟生成专业级AI美女图
淘客系统数据库分库分表实践基于用户 ID 与时间维度的 Sharding 策略大家好我是 微赚淘客系统
0 的研发者省赚客在高并发、大数据量场景下单库单表早已无法满足淘客系统的业务需求。
微赚淘客系统
0 在日订单量突破千万级后我们对核心数据表如订单表、佣金流水表进行了分库分表改造采用基于用户 ID 与时间维度的复合 Sharding 策略有效提升了系统吞吐能力与查询效率。
Sharding 策略设计原则我们的核心目标是写入均匀避免热点写入导致单库负载过高查询高效支持按用户 ID 快速定位分片同时兼顾时间范围查询扩容平滑未来可线性扩展分库数量而不影响历史数据。
为此我们选择用户 ID 哈希取模 时间范围分表的混合策略。
具体如下分库依据user_id % db_count确保同一用户的所有数据落在同一库便于事务一致性分表依据按月分表如order_
order_202601便于冷热分离与归档。
ShardingSphere 配置实现我们使用 Apache ShardingSphere
x 作为中间件通过 Java 配置方式定义分片规则。
以下为关键代码示例packagejuwatech.cn.sharding.config;importorg.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;importorg.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;importorg.springframework.stereotype.Component;importjava.util.Collection;importjava.util.stream.Collectors;ComponentpublicclassUserIdPreciseShardingAlgorithmimplementsPreciseShardingAlgorithmLong{privatestaticfinalintDB_COUNT8;OverridepublicStringdoSharding(CollectionStringavailableTargetNames,PreciseShardingValueLongshardingValue){LonguserIdshardingValue.getValue();Stringtargetds(userId%DB_COUNT);if(availableTargetNames.contains(target)){returntarget;}thrownewIllegalArgumentException(No database found for user_id: userId);}}时间维度分表算法如下packagejuwatech.cn.sharding.algorithm;importorg.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;importorg.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;importorg.springframework.stereotype.Component;importjava.time.LocalDateTime;importjava.time.format.DateTimeFormatter;importjava.util.Collection;ComponentpublicclassOrderTablePreciseShardingAlgorithmimplementsPreciseShardingAlgorithmLocalDateTime{privatestaticfinalDateTimeFormatterFORMATTERDateTimeFormatter.ofPattern(yyyyMM);OverridepublicStringdoSharding(CollectionStringavailableTargetNames,PreciseShardingValueLocalDateTimeshardingValue){StringsuffixshardingValue.getValue().format(FORMATTER);StringtargetTablet_order_suffix;if(availableTargetNames.contains(targetTable)){returntargetTable;}// 若目标表不存在可动态创建或回退到默认表生产环境建议预建returnt_order_default;}}
Spring Boot 集成配置在application.yml中配置数据源与分片规则spring:shardingsphere:datasource:names:ds0,ds1,ds2,ds3,ds4,ds5,ds6,ds7ds0:type:com.zaxxer.hikari.HikariDataSourcedriver-class-name:com.mysql.cj.jdbc.Driverjdbc-url:jdbc:mysql://db
juwatech.cn:3306/order_db_0username:rootpassword:***# ... ds1 ~ ds7 类似配置rules:sharding:tables:t_order:actual-data-nodes:ds$-{
.7}.t_order_$-{
.202612}database-strategy:standard:sharding-column:user_idprecise-algorithm-class-name:juwatetech.cn.sharding.config.UserIdPreciseShardingAlgorithmtable-strategy:standard:sharding-column:create_timeprecise-algorithm-class-name:juwatech.cn.sharding.algorithm.OrderTablePreciseShardingAlgorithm注意actual-data-nodes中的时间范围需根据业务预估提前配置避免运行时找不到表。
DAO 层与实体类示例订单实体类需包含分片键packagejuwatech.cn.entity;importjava.time.LocalDateTime;publicclassOrder{privateLongid;privateLonguserId;// 分库键privateLocalDateTimecreateTime;// 分表键privateStringorderNo;privateLongcommission;// getters setters}MyBatis Mapper 示例packagejuwatech.cn.mapper;importjuwatech.cn.entity.Order;importorg.apache.ibatis.annotations.Insert;importorg.apache.ibatis.annotations.Mapper;importorg.apache.ibatis.annotations.Select;MapperpublicinterfaceOrderMapper{Insert(INSERT INTO t_order (user_id, create_time, order_no, commission) VALUES (#{userId}, #{createTime}, #{orderNo}, #{commission}))voidinsert(Orderorder);Select(SELECT * FROM t_order WHERE user_id #{userId} AND create_time BETWEEN #{startTime} AND #{endTime})ListOrderfindByUserIdAndTimeRange(Param(userId)LonguserId,Param(startTime)LocalDateTimestartTime,Param(endTime)LocalDateTimeendTime);}由于 ShardingSphere 能自动路由上述查询无需手动指定表名只要传入user_id和create_time中间件即可定位到具体库表。
五、
注意事项与优化点跨分片查询限制避免SELECT * FROM t_order WHERE commission 100这类无分片键的查询会导致全库扫描分页性能大偏移量分页如LIMIT 100000, 20性能差建议改用游标分页基于id lastIdDDL 同步新增字段需通过运维脚本同步到所有分库分表时间分表预建建议通过定时任务每月初自动创建下月表避免运行时异常。
效果验证上线后单库 QPS 从 12,000 降至 1,500 以下慢查询下降 92%订单写入延迟稳定在 10ms 内。
复合 Sharding 策略在保证数据隔离的同时显著提升了系统可扩展性。
本文著作权归 微赚淘客系统