【电商核心业务实战】(5) 订单系统分库分表⽅案设计与实现
电商核心业务实战 · 系列文章目录(1) 电商项目核心订单系统设计与实现(2) 电商促销流程设计与实现(3) 分布式唯一ID 实战(4) 订单系统读写分离方案设计与实现(5) 订单系统分库分表方案设计与实现(6) 订单系统历史数据归档方案设计与实现(7) 电商项目订单支付实战(8) 使用RocketMQ优化订单超时取消流程(9) 分布式事务在电商项目中的应用场景分析与实战分库分表除了访问MySQL的并发问题还要解决海量数据的问题很多的时候我们会使⽤分布式的存储集群因为MySQL本质上是⼀个单机数据库所以很多场景下其并不适合存储TB级别以上的数据。但是绝⼤部分电商企业的在线交易类业务⽐如订单、⽀付相关的系统还是⽆法离开MySQL的。原因是只有MySQL 之类的关系型数据库才能提供⾦融级的事务保证。⽬前的分布式事务的各种解法⽅案多少都有些不够完善。虽然 MySQL ⽆法⽀持这么⼤的数据量以及这么⾼的并发需求但是交易类系统必须⽤它来保证数据⼀致性那么如何才能解决这个问题呢这个时候我们就要考虑分⽚也就是拆分数据。如果⼀个数据库⽆法⽀撑1TB的数据那就把它拆分成100个库每个库就只有10GB的数据了。这种拆分操作就是MySQL的分库分表操作。如何规划分库分表以订单表为例⾸先,我们需要思考的问题是选择分库还是分表或者两者都有分库就是把数据拆分到不同的MySQL 数据库实例中分表就是把数据拆分到⼀个数据库的多张表⾥⾯。在考虑到底是选择分库还是分表之前,我们需要⾸先明确⼀个原则能不拆就不拆。原因很简单数据拆得越分散,并发和维护就越麻烦系统出问题的概率也就越⼤。遵循上⾯这个原则还需要进⼀步了解哪种情况适合分表哪种情况适合分库。选择分库或是分表的⽬的是解决如下两个问题。第⼀是为了解决因数据量太⼤⽽导致查询慢的问题。这⾥所说的“查询”主要是事务中的查询和更新操作因为只读的查询可以通过缓存和主从分离来解决。分表主要⽤于解决因数据量⼤⽽导致的查询慢的问题。第⼆是为了应对⾼并发的问题。如果⼀个数据库实例撑不住就把并发请求分散到多个实例中所以分库可⽤于解决⾼并发的问题。简单地说如果数据量太⼤就分表如果并发请求量⾼就分库。⼀般情况下,我们的解决⽅案⼤都需要同时做分库分表,我们可以根据预估的并发量和数据量分别计算应该拆分成多少个库以及多少张表。商城订单服务的实现数据量在设计系统我们预估订单的数量每个⽉订单2000W⼀年的订单数可达2.4亿。⽽每条订单的⼤⼩⼤致为1KB按照我们在MySQL中学习到的知识为了让B树的⾼度控制在⼀定范围保证查询的性能每个表中的数据不宜超过2000W。在这种情况下为了存下2.4亿的订单我们似乎应该将订单表分为1612往上取最近的2的幂张表。但是这样设计有个问题我们只考虑了订单表没有考虑订单详情表。我们预估⼀张订单下的商品平均为10个那既是⼀年的订单详情数可以达到24亿同样以每表2000W记录计算应该订单详情表为128120往上取最近的2的幂张⽽订单表和订单详情表虽然记录数上是⼀对⼀的关系但是表之间还是⼀对⼀订单表也要为128张。经过再三分析我们最终将订单表和订单详情表的张数定为32张。这会导致订单详情表单表的数据量达到8000W为何要这么设计呢原因我们后⾯再说。选择分片键既然决定订单系统分库分表则还有⼀个重要的问题那就是如何选择⼀个合适的列作为分表的依据该列我们⼀般称为分⽚键Sharding Key)。选择合适的分⽚键和分⽚算法⾮常重要因为其将直接影响分库分表的效果。选择分⽚键有⼀个最重要的参考因素是我们的业务是如何访问数据的⽐如我们把订单ID作为分⽚键来拆分订单表。那么拆分之后,如果按照订单ID来查询订单,就需要先根据订单ID和分⽚算法,计算所要查的这个订单具体在哪个分⽚上也就是哪个库的哪张表中然后再去那个分⽚执⾏查询操作即可。但是当⽤户打开“我的订单”这个⻚⾯的时候它的查询条件是⽤户ID由于这⾥没有订单ID因此我们⽆法知道所要查询的订单具体在哪个分⽚上也就没法查了。如果要强⾏查询的话那就只能把所有的分⽚都查询⼀遍再合并查询结果这个过程⽐较麻烦⽽且性能很差对分⻚也很不友好。那么如果是把⽤户ID作为分⽚键呢答案是也会⾯临同样的问题使⽤订单ID作为查询条件时⽆法定位到具体的分⽚上。这个问题的解决办法是在⽣成订单ID的时候把⽤户ID的后⼏位作为订单ID的⼀部分。这样按订单ID查询的时候就可以根据订单ID中的⽤户ID找到分⽚。 所以在我们的系统中订单ID从唯⼀ID服务获取ID后还会将⽤户ID的后两位拼接形成最终的订单ID。然⽽系统对订单的查询⽅式肯定不只是按订单ID或按⽤户ID查询两种⽅式。⽐如如果有商家希望查询⾃家家店的订单有与订单相关的各种报表。对订单做了分库分表就没法解决了。这个问题⼜该怎么解决呢⼀般的做法是把订单⾥数据同步到其他存储系统中然后在其他存储系统⾥解决该问题。⽐如可以再构建⼀个以店铺ID作为分⽚键的只读订单库专供商家使⽤。或者数据同步到Hadoop分布式⽂件系统HDFS中然后通过⼀些⼤数据技术⽣成与订单相关的报表。在分⽚算法上我们知道常⽤的有按范围⽐如时间范围分⽚哈希分⽚查表法分⽚。我们这⾥直接使⽤哈希分⽚对表的个数32直接取模⼀旦做了分库分表就会极⼤地限制数据库的查询能⼒原本很简单的查询分库分表之后可能就没法实现了。分库分表⼀定是在数据量和并发请求量⼤到所有招数都⽆效的情况下我们才会采⽤的最后⼀招。具体实现如何在代码中实现读写分离和分库分表呢⼀般来说有三种⽅法。纯⼿⼯⽅式修改应⽤程序的DAO层代码定义多个数据源在代码中需要访问数据库的每个地⽅指定每个数据库请求的数据源。组件⽅式使⽤像Sharding-JDBC 这些组件集成在应⽤程序内⽤于代理应⽤程序的所有数据库请求并把请求⾃动路由到对应的数据库实例上。代理⽅式:在应⽤程序和数据库实例之间部署⼀组数据库代理实例,⽐如Atlas或Sharding-Proxy。对于应⽤程序来说,数据库代理把⾃⼰伪装成⼀个单节点的MySQL实例,应⽤程序的所有数据库请求都将发送给代理代理分离请求然后将分离后的请求转发给对应的数据库实例。在这三种⽅式中⼀般推荐第⼆种使⽤分离组件的⽅式。采⽤这种⽅式,代码侵⼊⾮常少,同时还能兼顾性能和稳定性。如果应⽤程序是⼀个逻辑⾮常简单的微服务,简单到只有⼏个SQL,或者应⽤程序使⽤的编程语⾔没有合适的读写分离组件,那么也可以考虑通过纯⼿⼯的⽅式。不推荐使⽤代理⽅式(第三种⽅式原因是代理⽅式加⻓了系统运⾏时数据库请求的调⽤链路,会造成⼀定的性能损失⽽且代理服务本身也可能会出现故障和性能瓶颈等问题。代理⽅式有⼀个好处对应⽤程序完全透明。所以在我们的订单服务中使⽤了第⼆种⽅式引⼊了Sharding-JDBC考虑要同时⽀持读写分离和分库分表配置如下在分⽚键的选择上订单信息的查询往往会指定订单的ID或者⽤户ID所以oms_order的分⽚键为表中的id、member_id两个字段。⽽oms_order_item表通过order_id字段和oms_order的id进⾏关联所以它的分⽚键选择为order_id。对应在代码中有专⻔的分⽚算法实现类OmsOrderShardingAlgorithm和OmsOrderItemShardingAlgorithm分别⽤于对订单和订单详情进⾏分⽚。其中的OmsOrderShardingAlgorithm负责对订单进⾏分⽚在实现上获得订单的Id或者member_id的后两位然后对表的个数进⾏取模以定位到实际的物理oms_order表。OmsOrderItemShardingAlgorithm负责对订单详情进⾏分⽚实现上与OmsOrderShardingAlgorithm类似。

相关新闻

大模型评测实战:价格与性能的真相,如何科学选型提升开发效率

大模型评测实战:价格与性能的真相,如何科学选型提升开发效率

1. 一次“昂贵”的模型评测之旅:缘起与目标最近几个月,AI圈子里关于各种大模型的消息就没停过。从OpenAI的GPT-4o到Google的Gemini 2.0 Flash,再到国内DeepSeek的V3,感觉每周都有新选手登场。作为一个长期混迹在开源社区和商业AI服…

2026/10/30 21:54:52 阅读更多 →
宇树科技中签率远低于长鑫,“大疆式”打法能否助其突破人形机器人困局?

宇树科技中签率远低于长鑫,“大疆式”打法能否助其突破人形机器人困局?

【宇树科技中签结果引关注】宇树科技中签结果揭晓,网上中签号码共19414个,最终中签率约为0.018%,远低于长鑫科技0.47%的中签率。中签结果公布后,社交平台掀起晒单潮。若对标年内科创板新股首日466.61%的平均涨幅,单签盈…

2026/10/25 13:07:53 阅读更多 →
DeepSeek Harness 开发者预览版开启:一切皆插件,运行可追溯!

DeepSeek Harness 开发者预览版开启:一切皆插件,运行可追溯!

DeepSeek Harness 开发者预览版发布DeepSeek Harness 目前面向全球的智能体框架开发者开启了开发者预览版,同时开放了源代码。每一项功能都是一个插件,可进行替换或重新组合,包括模型、工具、技能、会话、沙箱、存储、循环、调度以及用户界面…

2026/10/30 1:30:29 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/10/31 0:19:11 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/10/31 10:20:19 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/10/31 10:20:23 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/10/31 0:59:28 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/10/31 10:30:19 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/10/31 9:29:43 阅读更多 →

日新闻

周新闻

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/31 18:03:41 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/31 11:00:40 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/31 0:09:01 阅读更多 →