疏影横斜水清浅,暗香浮动月黄昏。
1 前言
在电商项目开发中,订单系统是整个项目的核心,那么一个订单系统该如何着手设计并提供对应的能力呢,这是一个值得深思的问题。本文将结合项目实践经验,从设计角度出发,根据实际的业务要求着重分享几个核心的业务关键点和技术关键点。
2 设计理念和技术选型
订单系统是一个核心系统,其技术基本要求如下:
- 1 高可用性,需要保证系统的4个9,服务需要采用集群部署,并且能够实现故障转移。
- 2 高并发,每秒钟支持1000+的订单创建,需要使用异步处理和流量削峰。
- 3 数据一致性,通过分布式事务和补偿机制保证核心业务的数据一致性。
- 4 可扩展性,需要采用微服务架构,模块化设计实现业务开发的快速迭代。
对于技术选型,需要采用目前主流的框架。基础框架为SpringBoot3.x+SpringCloudAlibaba
,数据存储和缓存采用 MySQL8+Redis7
,消息队列使用rabbitmq
实现异步解耦,分库分表工具使用 ShardingSphere5
。此外还要有监控体系,推荐采用 Prometheus + Grafana
。对于日志查询,可以使用 ELK
进行搭建。项目中使用的工具类为 Hutool
, ORM
框架采用 mybatis-plus
。
3 核心模块设计
3.1 订单创建
订单创建时,需要防止订单的重复提交,保证幂等性。采用可靠的生单方案,推荐根据业务编号前缀和雪花算法生成订单号和订单明细号。
为了防止订单重复提交,在提交订单之前,需要先获取订单的请求号。在创建订单时需要判断订单号是否存在,防止订单的重复创建。此外这里的雪花算法生成算法使用 Hutool
里面的 Snowflake
进行创建。

3.2 订单状态流转
通常情况下,订单的状态如下所示:
scss
[待支付] → (支付成功) → [已支付] → [退款中] → [退款完成|部分退款]
↘ (超时未支付) → [已取消]
↘ (用户关单) → [已关闭]
对于状态的流转,可以使用状态机 Spring StateMachine 来控制状态的流转,但是在实际的操作中,很少采用这样的方式,因为实际状态相对比较复杂。通常会在业务代码中实现状态的流转和控制。
3.3 库存扣减方案
对于库存的扣减的方案,总的来说可以分为数据库扣减或者数据库+redis缓存的方式进行扣减:
- 数据库扣减
bash
1 根据商品id查询库存,校验商品的状态以及sku的状态
update tb_good_stock set stock_num=stock_num-count where sku_id= skuId and stock_num>= count;
-
缓存扣减库存
使用redis扣减库存,可以结合lua脚本操作商品库存的批量扣减,并且使用异步任务+操作日志将库存变化同步到数据库中。
根据业务的实际情况设计扣库存,库存扣减的时机分为两种,下单扣减库存和支付时扣减库存:
扣减方式 | 优势 | 缺点 |
---|---|---|
下单时扣减库存 | 买家只要下单就能够买到商品 | 库存紧张时,买家拍下不付款,会影响其他买家下单。可能会存在恶意占库存的情况,导致商品售罄给卖家造成损失。 |
支付时扣减库存 | 库存不会长时间占用,当库存紧张时,会有更多机会买到商品。 | 用户支付成功后扣减库存,会出现扣减失败的方式,系统需要进行自动关单并退款,影响买家体验。 |
3.4 分布式事务
对于单机服务,可以使用本地事务来解决问题,但是对于微服务项目来说,就需要使用分布式事务。对于分布式事务,强一致性的场景可以使用 rocketmq 的事务消息或者使用 seta 来实现,对于一般的场景,可以使用本地消息表的方式来实现最终一致性。

3.5 分库分表方案
对于订单数据,订单表和订单明细表是需要进行分库分表的,分库的策略根据 userId
进行分库,分表的策略是根据 createTime
进行分表。此外,订单表和订单明细表的分库分表策略要保持一致,方便进行表关联的操作。另外,退款单表和退款明细表的分库分表策略和订单的策略保持一致。如果退款数据量比较小的话,可以使用分表策略即可,无需分库。

4 性能优化和任务补偿
4.1 任务补偿
对于任务补偿,主要是用于关闭超时未支付的订单,此外还要重试处理中的退款单。
4.2 性能优化
- 1 对于热点数据,使用redis 进行缓存,比如字典数据,用户经常查询的订单。
- 2 数据的读分离,通过
ShardingSphere
不仅可以实现分库分表,还可以通过配置实现读写分离。 - 3 索引优化,对订单表里面经常的查询字段,可以建立联合索引,方便数据的查询。
- 4 针对订单服务的接口,需要监控服务的
TPS/QPS
数据,通过链路分析查询业务的卡点,进行技术优化。 - 5 监听
mysql
数据库的使用情况,线程池的使用效率以及慢sql
数据,进行配置和查询的优化处理。
5 总结
本文通过订单服务的创建实践,介绍了订单系统设计的重点和核心内容。在设计系统的过程中中,会用到各种技术知识,需要综合运用,根据业务的实际需要进行取舍。通过订单系统将各种技术组合使用,实现业务系统的高效运行,提供可靠的服务能力。本文通过数据项目 github
地址 springboot-auth。