通达快递系统设计
1 并发量计算
系统的并发量可以从三个方面进行计算:
A 用户下单并发量:
每天 50 万订单,下单时间平均按 8 小时计算,则平均并发数量为:50 万/(8 * 3600)= 17
B 快递员位置上报并发量:
假设一个快递员没有能够处理五十个订单,则需要 1 万个快递员,那么 30 秒内有一万个位置上报请求,则位置上报并发量为 10000/30 秒= 350
C 订单状态修改并发量:
一个订单需要记录状态两次,共需要记录 100 万次,按 8 小时计算,则平均并发数量为:2*50 万/(8 * 3600)= 35
综合考虑上面三项,系统总的平均并发量:400QPS;峰值并发量按平均并发量的 10 倍计算,在峰值并发量为 4000QPS。系统并发量谈不上高,也谈不上低,为中等水平。
2 用例图
系统用例图如图 1 所示。
图 1. 系统用例图
本系统有三类使用者,分别是用户、管理员和快递员。其中,“用户”是需要发送快递的人员,快递员是负责送快递的人员,这两类人是系统服务的使用者。管理员是快递系统的管理员,为系统业务提供支持。系统主要功能包括订单管理、抢单、位置管理、支付、通知和系统管理等功能。其中,订单管理和抢单是系统的核心功能。
用户在系统下单,需要用到订单管理、支付等功能。快递员接收订单,主要用到抢单、位置管理等功能。通知功能是一个通用功能,用户和快递员都需要此功能。系统需要通知快递员订单信息,也需要通知用户订单状态。系统管理员需要对网站进行管理,需要系统管理功能。此功能是个基础功能,对下单、抢单等业务起支撑作用。
3 活动图
系统活动图如图 2 所示。
图 2. 系统活动图
系统的主要活动是下单和抢单。用户发起下单活动。快递员负责抢单活动。
用户通过 APP 或网页发起下单活动。网站的订单管理微服务收到下单请求后创建订单,然后系统在终端上提示用户进行支付。用户执行支付操作,由服务器端的支付微服务进行处理。支付操作失败,则提示用户“支付失败”;支付成功后由抢单微服务进行处理;抢单微服务会获取 5km 范围内的快递员信息,和订单信息打包后由通知微服务下发到快递员。
快递员收到订单后发起抢单活动,抢单成功以后进入派送流程。快递员会根据货物送货情况手动更改订单状态。快递员使用的终端 APP 会自动定时上报其位置信息。
4 部署图
系统部署图如图 3 所示。
图 3. 系统部署架构图
用户请求首先到达 Nginx,由 Nginx 进行负载均衡,将请求发送到某一个网关实例。微服务网关采用 SpringCloud 家族的 Spring Gateway,由若干台机器构成一个小型网关集群。
微服务集群包括订单管理微服务、抢单微服务、位置管理微服务、支付微服务、通知微服务和系统管理微服务。每个微服务有两个实例。抢单微服务和通知微服务将消息发送到 RocketMQ,实现异步处理。位置管理微服务将快递员的实时位置数据缓存在 Redis 上。抢单微服务从 Redis 获取 5km 范围内的所有快递员的位置信息。本系统属于即时物流系统,对延迟非常敏感,Rocket 和 Redis 可以显著提高系统的处理速度,降低延迟。
MySQL 数据库采用主从复制。快递业务具有写多读少的特点,所以采用一主一从模式,主 MySQL 负责写,从 MySQL 负责读。系统实时性要求高,故采用异步复制。根据系统的并发量估计,采用两台 MySQL 作为主 MySQL,负责写入操作,即可满足系统需求。
MySQL 的主从复制可以采用基于 GTID 的主从异步复制模式。 GTID 的工作原理如下:
1、master 更新数据时,会在事务前产生 GTID,一同记录到 binlog 日志中。
2、slave 端的 i/o 线程将变更的 binlog,写入到本地的 relay log 中。
3、sql 线程从 relay log 中获取 GTID,然后对比 slave 端的 binlog 是否有记录。
4、如果有记录,说明该 GTID 的事务已经执行,slave 会忽略。
5、如果没有记录,slave 就会从 relay log 中执行该 GTID 的事务,并记录到 binlog。
6、在解析过程中会判断是否有主键,如果没有就用二级索引,如果没有就用全部扫描。
此种模式的优点:
1.一个事务对应一个唯一 ID,一个 GTID 在一个服务器上只会执行一次
2.GTID 是用来代替传统复制的方法,GTID 复制与普通复制模式的最大不同就是不需要指定二进制文件名和位置
3.减少手工干预和降低服务故障时间,当主机挂了之后通过软件从众多的备机中提升一台备机为主机。
5 时序图
系统时序图如图 4 所示。
图 4. 系统下单/抢单时序图
用户先发起下单活动,请求到达订单管理微服务。订单创建成功后,用户发起支付活动。支付成功后,抢单微服务发起抢单活动,通知快递员进行抢单活动。快递员抢单成功后,根据货物发送情况更新订单状态。
6 订单状态图
订单状态图如图 5 所示。
图 5. 系统订单状态图
一个完整的快递活动由若干节点组成,订单就是用来描述快递活动的,所以订单是有状态的,对应着订单活动中的重要节点。订单是系统最重要的对象,一个订单对应一个完整的快递活动。订单把用户和快递员联系起来,用户和快递员的活动影响着订单的状态。
订单状态设计如下:初始状态、已支付、支付失败、取消、派送中、已送达、待收货、已收货。
一个订单从用户发起请求开始存在,系统会根据用户请求创建订单对象病进行初始化,此时订单处于“初始状态”。用户随后会进行支付活动,支付的结果可能是成功,也可能是失败,对应订单的两个状态“已支付”和“支付失败”。此过程中,用户可能会取消订单,此时订单处于“取消”状态。
快递员的活动影响着订单的状态。快递员接单以后,订单处于“派送中”状态。快递送到用户以后,订单处于“已送达”状态,随后处于“待确认”状态,即等待用户确认接收。用户确认接收以后,订单处于“已确认”状态。但通常情况下,用户不会进行确认接收。此时系统在一定时间后会自动将订单转变为“已确认”状态。
评论