news 2026/4/18 6:23:11

淘客系统数据库分库分表实践:基于用户 ID 与时间维度的 Sharding 策略

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
淘客系统数据库分库分表实践:基于用户 ID 与时间维度的 Sharding 策略

淘客系统数据库分库分表实践:基于用户 ID 与时间维度的 Sharding 策略

大家好,我是 微赚淘客系统3.0 的研发者省赚客!

在高并发、大数据量场景下,单库单表早已无法满足淘客系统的业务需求。微赚淘客系统3.0 在日订单量突破千万级后,我们对核心数据表(如订单表、佣金流水表)进行了分库分表改造,采用基于用户 ID 与时间维度的复合 Sharding 策略,有效提升了系统吞吐能力与查询效率。

一、Sharding 策略设计原则

我们的核心目标是:

  • 写入均匀:避免热点写入导致单库负载过高;
  • 查询高效:支持按用户 ID 快速定位分片,同时兼顾时间范围查询;
  • 扩容平滑:未来可线性扩展分库数量而不影响历史数据。

为此,我们选择用户 ID 哈希取模 + 时间范围分表的混合策略。具体如下:

  • 分库依据user_id % db_count,确保同一用户的所有数据落在同一库,便于事务一致性;
  • 分表依据:按月分表,如order_202512order_202601,便于冷热分离与归档。

二、ShardingSphere 配置实现

我们使用 Apache ShardingSphere 5.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;@ComponentpublicclassUserIdPreciseShardingAlgorithmimplementsPreciseShardingAlgorithm<Long>{privatestaticfinalintDB_COUNT=8;@OverridepublicStringdoSharding(Collection<String>availableTargetNames,PreciseShardingValue<Long>shardingValue){LonguserId=shardingValue.getValue();Stringtarget="ds"+(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;@ComponentpublicclassOrderTablePreciseShardingAlgorithmimplementsPreciseShardingAlgorithm<LocalDateTime>{privatestaticfinalDateTimeFormatterFORMATTER=DateTimeFormatter.ofPattern("yyyyMM");@OverridepublicStringdoSharding(Collection<String>availableTargetNames,PreciseShardingValue<LocalDateTime>shardingValue){Stringsuffix=shardingValue.getValue().format(FORMATTER);StringtargetTable="t_order_"+suffix;if(availableTargetNames.contains(targetTable)){returntargetTable;}// 若目标表不存在,可动态创建或回退到默认表(生产环境建议预建)return"t_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://db0.juwatech.cn:3306/order_db_0username:rootpassword:***# ... ds1 ~ ds7 类似配置rules:sharding:tables:t_order:actual-data-nodes:ds$->{0..7}.t_order_$->{202501..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}")List<Order>findByUserIdAndTimeRange(@Param("userId")LonguserId,@Param("startTime")LocalDateTimestartTime,@Param("endTime")LocalDateTimeendTime);}

由于 ShardingSphere 能自动路由,上述查询无需手动指定表名,只要传入user_idcreate_time,中间件即可定位到具体库表。

五、注意事项与优化点

  1. 跨分片查询限制:避免SELECT * FROM t_order WHERE commission > 100这类无分片键的查询,会导致全库扫描;
  2. 分页性能:大偏移量分页(如LIMIT 100000, 20)性能差,建议改用游标分页(基于id > lastId);
  3. DDL 同步:新增字段需通过运维脚本同步到所有分库分表;
  4. 时间分表预建:建议通过定时任务每月初自动创建下月表,避免运行时异常。

六、效果验证

上线后,单库 QPS 从 12,000 降至 1,500 以下,慢查询下降 92%,订单写入延迟稳定在 10ms 内。复合 Sharding 策略在保证数据隔离的同时,显著提升了系统可扩展性。

本文著作权归 微赚淘客系统3.0 研发团队,转载请注明出处!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/8 2:27:01

返利公众号消息推送的可靠性保障:模板消息队列化与送达状态追踪

返利公众号消息推送的可靠性保障&#xff1a;模板消息队列化与送达状态追踪 大家好&#xff0c;我是 微赚淘客系统3.0 的研发者省赚客&#xff01; 在微赚淘客系统3.0中&#xff0c;用户完成订单后需通过微信公众号模板消息实时通知返利到账。然而&#xff0c;直接调用微信接…

作者头像 李华
网站建设 2026/4/4 0:26:39

JAVA停车系统源码,开启畅停新体验

以下是一个基于Java的停车系统源码示例框架&#xff0c;结合了核心功能与现代技术架构&#xff0c;可实现“畅停随行&#xff0c;轻松出行”的智能化体验&#xff1a; 一、系统架构设计 技术选型 后端框架&#xff1a;Spring Boot 2.7.x&#xff08;简化配置&#xff0c;快速…

作者头像 李华
网站建设 2026/4/13 17:26:54

Java毕设选题推荐:基于SpringBoot的蔬菜种植管理系统设计与实现种植环境监测、种子与种苗管理【附源码、mysql、文档、调试+代码讲解+全bao等】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/4/16 14:09:18

用户注册流程的深度测试验证指南:面向测试工程师的实践手册

‌ 用户注册是绝大多数应用与用户建立连接的第一步&#xff0c;其流程的顺畅度、安全性和稳定性直接影响用户的第一印象和转化率。作为软件测试工程师&#xff0c;对注册流程进行系统化、精细化的验证至关重要。本指南将聚焦于用户注册流程的各个关键环节&#xff0c;提供详尽的…

作者头像 李华