资讯动态

外卖系统+E升级实战:从单体架构到高并发智能调度

发布时间:2026/10/18 7:17:30 来源:尧图企业网站定制
“外卖系统E”这个项目名第一次看到的人多少会有点摸不着头脑尤其是那个“E”到底是什么意思。我拿到这个项目需求的时候第一反应也是去猜这个字母背后想表达的东西。实际上这是一个比较典型的外卖业务系统升级改造项目标题里的“E”在我们内部沟通中最终被拆成了四层含义Enhanced增强、Efficiency效率、Ecosystem生态、Experience体验。简单来说就是对外卖系统做一次整体升级让它不再是单纯的下单、接单、配送的工具而是变成一个能承载更多业务场景、能通过数据和算法提效、能开放给第三方生态伙伴的完整平台。这个项目适合谁参考如果你正在做本地生活类系统、电商交易系统或者你们公司的外卖/配送平台已经到了“加功能加不动、高峰期扛不住、数据用不上”的阶段那这篇内容应该能给你不少启发。我会把我在这类项目里的思路、方案选型逻辑、关键环节的实现方式以及踩过的实打实的坑都拆开揉碎写清楚。不管是技术管理者还是核心开发都能在里面找到可以直接拿去用的东西。1. 项目定位先搞清楚“E”到底要加什么很多系统升级项目失败不是因为技术不行而是因为一开始就没想清楚“升级到底要解决什么问题”。“外卖系统E”如果只是理解为“把系统做得更花哨”那这个项目从一开始就走偏了。我在启动这个项目前团队内部花了很长时间做业务复盘把过去两年外卖系统在运营中暴露出来的问题一条条列出来最后总结成四个升级方向。1.1 传统外卖系统的典型痛点先看传统外卖系统普遍存在的几个问题。第一个是订单峰值扛不住中午和晚上的用餐高峰期订单量可能是平时流量的几十倍系统在扩展性不足的情况下经常出现下单超时、支付回调丢失、数据库锁等待严重的状况。第二个是骑手调度靠人工经验和大致估算调度员盯着地图手动派单高峰期手忙脚乱骑手空跑率高、配送超时率高。第三个是商户和平台之间的数据不互通商户不知道自己的菜品在平台上的真实转化率平台也拿不到商户的实时库存和出餐状态是典型的“数据孤岛”。第四个是用户端功能单一除了下单就是查订单缺乏会员体系、个性化推荐、营销活动的支撑复购率上不去。这些问题不是靠加几个功能就能解决的它们涉及系统架构、数据模型、算法调度、开放接口等多个层面。所以“E”不是一个新功能模块的名字而是对整个系统升级方向的抽象概括。我在立项报告里把这四个痛点分别映射到Enhanced、Efficiency、Ecosystem、Experience四个关键词上后面的所有工作都围绕这四个词展开。1.2 “E”的四层含义拆解Enhanced增强对应的是系统底座的升级。核心链路要做服务化拆分把订单、支付、调度、结算等核心模块拆成独立服务各自能独立扩展高峰期按压力单独扩容。缓存、消息队列、分库分表这些基础设施要重新设计不能继续靠单体应用硬扛。Efficiency效率对应的是智能化调度。原来人工派单的方式要替换为基于算法的自动派单系统骑手位置实时上报订单根据距离、路况、骑手负载、顺路程度做综合评分自动分配。目标是把骑手空驶时间降下来把平均配送时长降下来同时保证每位骑手的接单量相对均衡。Ecosystem生态对应的是开放平台。外卖业务不可能只靠平台自己做要接入第三方配送运力、供应链服务商、营销服务商还要开放商户自助化的经营工具。这个层面要做的是标准化的开放接口、清晰的服务协议、便捷的开发者接入流程让外部系统能够安全地接入平台数据和服务。Experience体验对应的是用户端和商户端的产品升级。用户端要支持个性化和会员化运营商户端要有经营数据看板、菜品分析、营销工具让两端用户都觉得系统“懂我”。这一层离业务最近也最容易被技术团队忽略。1.3 我为什么选择“先优化核心链路再补生态”在确定四个升级方向之后就面临一个先后顺序的问题。很多团队会选择“新功能优先”先把用户端做得好看一点、加一些营销玩法因为这些功能领导容易感知、上线有亮点。但我的判断是如果核心链路撑不住所有新功能上线了也是给故障添砖加瓦。用户点餐下单都超时会员体系再丰富也没用。所以这个项目的路线图被定成了三个阶段。第一阶段夯实底座拆服务、压测、改进存储和缓存把订单主流程的稳定性和扩展性做到位第二阶段上线智能调度系统替换人工派单同时建立骑手轨迹和站点数据体系这是效率和体验的基础第三阶段搭建开放平台提供商户API、第三方运力接入、数据服务等生态能力。三个阶段之间有依赖关系但也会并行推进部分项目比如商户经营看板这类不依赖核心链路的业务模块可以在第二阶段就提前启动。这个顺序背后有一个核心逻辑技术投入要优先放在用户最直接感知的地方。用户感知最深的不是某个花哨页面而是“下单是否顺畅”、“外卖是否准时送到”。所以订单主流程和配送效率就是最高优先级这个判断后来被证明是正确的改造上线后客诉率下降非常明显也给了团队继续做生态类项目的信心。2. 核心方案拆解与技术选型逻辑项目方向定好之后就到了具体技术方案设计阶段。这一步是整个项目里最考验经验的部分因为“怎么做”往往比“做什么”更能决定成败。我在这部分按模块拆解一下技术方案每块都会说明选型的逻辑以及不选某个方案的考虑。2.1 整体架构从单体到微服务的演进外卖系统在早期为了快速上线通常采用单体应用架构所有功能都在一个进程里数据库也是单库单表。这种架构在业务量小的时候开发效率极高但等到日订单量达到一定规模之后问题会集中爆发。早期单体应用的订单表和用户表、商户表在同一个数据库中高峰期高频访问导致数据库连接被占满任意一个慢查询都可能拖慢整个系统。因此这次升级的第一步就是服务化拆分。服务拆分的粒度需要拿捏。拆分过细会导致运维复杂度剧增拆分过粗又解决不了独立扩容的问题。我们当时是按“业务域”和“变化频率”两个维度划分的。订单域、支付域、配送域、商户域、用户域、营销域拆成独立的服务组每个服务组内再做适度细拆。这里有个经验不要一开始就追求极致的微服务粒度先把流量大、耦合深的核心链路服务拆出来非核心业务保持相对独立即可。拆分的同时我们把数据库也按照服务边界做了分库。订单库、支付库、商户库、用户库彼此独立服务之间不能直接访问对方的库必须走API。这看起来增加了不少通信开销但它保证了每个服务的数据模型可以按自己的节奏演进也避免了多服务共享数据库时的锁竞争问题。数据库拆分后我们对订单表做了分片按订单号哈希分到多个库实例这样单库压力就明显降下来了。2.2 关键技术选型框架、缓存、消息队列与调度算法技术选型这块我直接说我们最终采用的方案以及为什么是它。服务框架用的是目前Java系最成熟的微服务套件Spring Cloud 注册中心。它对分布式配置、服务发现、负载均衡、熔断降级都有比较成熟的解决方案团队上手成本低社区资料也多排查问题的时候能找到大量参考。如果团队是Go技术栈也有对应的成熟方案但因为我们团队的主语言是Java选它是最稳妥的而不是最炫的。缓存是Redis主要用来承接高频读取的场景比如菜单列表、店铺信息、骑手位置信息、热门分类数据等。这里要特别说明一下缓存策略不是所有数据都适合进缓存只有“读多写少”和“热点集中”的数据才有缓存价值。订单数据就不适合实时写进Redis做持久化它属于写多读少且对一致性要求极高的类型应该交给数据库和消息队列处理。缓存里存的订单状态只是用于用户端快速展示最终以数据库为准。消息队列我们选的是RocketMQ。在外卖这种业务场景里消息队列承担的任务极重订单状态变更通知、支付结果异步通知、骑手位置批量上报、用户行为日志收集、结算任务触发都要靠消息解耦。选RocketMQ而不是其他队列主要看中它的事务消息支持比较好这在订单和支付的对账场景里非常关键。事务消息能大致保证本地事务和消息发送的一致性问题减少后续对账的麻烦。当然这个选择也和团队已有基础相关如果你们团队运维能力有限或者业务体量没那么大用成熟的消息队列也没问题关键是机制要理解到位。智能调度算法这块我们没有一开始就上复杂的路径规划模型。那种全局最优解在城市级路网里有海量变量短时间内根本算不出来而且商家出餐时间预测也不够准算法给的结果可能还不如调度员经验。我们的第一步是做一个“基于规则评分”的派单引擎骑手端实时上报GPS坐标系统根据骑手当前位置和新订单的取餐点、送达点距离结合当前负载、方向一致性、预计出餐时间进行打分选出最合适的骑手。后续积累了足够的历史数据后再用机器学习优化出餐时间预测和骑手路径推荐。这样迭代路径最稳健业务效果也明显不是一口吃成胖子。技术组件选型方案核心原因适用前提服务框架Spring Cloud 注册中心成熟稳定、团队熟悉主语言为Java、已有微服务基础缓存Redis高性能、数据结构丰富缓存只放读多写少的数据消息队列RocketMQ事务消息支持好有订单和支付强一致需求的场景调度引擎规则评分模型的派单落地快、效果可控尚未积累大规模历史数据数据库MySQL 分库分表运维成熟、生态好业务体量达到需拆分的程度2.3 核心模块设计订单中心、支付与结算、配送调度订单中心是外卖系统的心脏核心要点是状态机设计。一个订单从创建到完成要经过待支付、已支付、商户确认、制作中、待取餐、配送中、已送达、已完成这些状态而且还要能处理退款、取消、异常单等分支状态。这里最容易犯的错误是状态流转逻辑散落在各个服务里导致不同服务对订单状态的理解不一致最后数据对不上。我们的设计是所有订单状态变更必须调用订单中心的统一状态机接口其他服务不能直接改订单状态只能发起变更请求。状态机里配置了合法的流转路径如果某个状态变更不在合法路径里直接拒绝并告警这样能有效避免脏状态数据。支付与结算模块可讲的细节很多。支付环节最关键的是异步回调的幂等处理支付通道返回回调时不能因为网络超时重试就重复入账。我们的处理是维护一张支付流水表每个支付请求生成唯一业务流水号回调处理时先查流水状态如果已经处理过就直接返回成功不再次更新订单和账户余额。这个幂等机制虽然基础但很多系统都是在线上出过重复打款事故之后才重视起来。结算模块则涉及商户、骑手、平台三方的分账我们采用T1日自动对账的方式每天晚上跑批把平台的订单数据、支付通道的流水、商户侧的交易数据三方做核对发现差异自动生成异常工单结算流程的自动化率做到了95%以上。配送调度模块的设计要从“人”的角度出发。调度系统不只是算距离还要考虑骑手的主观意愿和实际路况。我们设计了抢单和指派混合模式系统优先自动指派但如果系统评分差别不大也可以推送给多个骑手抢单保留一定的“人”的选择空间。骑手APP端每隔几秒上报一次GPS系统把位置信息写入Redis并做轨迹点压缩存储供后续分析用。调度算法的输入包括骑手位置、骑手负载、店铺出餐时间、用户位置、历史路况数据输出按综合评分排序的候选骑手列表。这个方案上线后高峰期的平均接单时长明显下降骑手空驶率也得到了控制是整个项目里业务收益最直接的一个模块。3. 实操过程核心环节的实现细节方案设计得再好落到实现上还是会有很多细节问题。这一章我会挑几个核心环节讲清楚它们具体是怎么一步步实现的。每一条都能直接照做或者至少能帮你在做自己系统时避开同样的坑。3.1 订单主流程的链路优化下单到接单的每一步先看用户下单这一个小动作背后发生了什么。用户提交订单请求首先到达网关层网关做身份校验、参数校验、频控校验然后调用订单服务的“创建订单”接口。订单服务此时要做几件事一是校验用户地址是否在配送范围内二是校验商户是否营业、菜品是否有库存三是计算订单金额并锁定商品库存四是生成订单记录并发送“订单创建成功”的消息到消息队列五是把订单信息同步到Redis缓存用于用户端快速查询。这些步骤里最需要仔细设计的是库存锁定。库存锁定如果处理不好会出现超卖问题。我们用Redis的Lua脚本实现了原子化的库存扣减脚本内部先检查库存是否充足再执行扣减整个过程原子执行避免并发扣减导致库存变成负数。但是这里有个坑如果锁了库存用户却不支付库存就会长时间被占用导致其他想买的用户买不到。所以下单和支付之间通常加一个超时机制比如15分钟内未支付就自动取消订单并回补库存。实现拆单回流用的是延迟队列订单创建时将“取消订单”的任务放入延迟队列如果到了设定的时间订单还没支付延迟任务就触发自动取消流程回补库存并释放资源。订单支付成功后的链路也至关重要。支付回调到达后支付服务先做幂等判断处理更新支付流水表状态然后发送“支付成功”的消息。订单服务收到消息后更新订单状态为“已支付”同时通知商户端有新订单。这里有一个经验之谈支付回调处理和后续订单状态更新之间一定要用消息队列解耦。支付服务只负责记录“收钱成功”这一事实后续的订单推进、通知商户、发送小票等动作都通过订阅消息异步完成。为什么这么做因为支付回调是支付通道直接调用我们的接口如果接口处理时间太长通道方可能超时重试而重试会加重数据库压力。用消息解耦后支付回调接口可以快速响应后续所有业务动作异步执行整体链路稳定不少。3.2 数据库表设计与订单状态机落地订单相关表的事务最容易出问题的在于“一张表存天下”。我记得很清楚初版订单表里只有一张表字段却有70多个用户信息、地址快照、商户信息、商品快照、配送信息、金额信息、优惠信息全部塞在一起。这样设计在初期开发省事但到了后期查询、更新、统计都极其痛苦。这次重构我们按DDD的思想把订单相关的数据结构做了拆分。核心拆分为订单主表、订单商品表、订单地址快照表、订单支付表、订单配送表、订单优惠明细表。订单主表只存订单维度最核心的信息订单号、用户ID、商户ID、订单状态、金额、支付方式等商品明细表存每件商品的名称、数量、单价、快照信息这个快照很重要因为商户修改菜品后历史订单仍然要显示下单时的商品内容所以必须做冗余快照配送表存配送地址、骑手信息、预计送达时间等。这种拆分方式带来的直接好处是日常高频的订单状态查询可以走主表订单详情页面通过主表ID关联查询明细表数据清晰且压力分散。订单状态机是防止脏数据的关键设施。我们的实现方式是用一个状态机的配置表记录每个状态允许流转到哪些状态代码里用枚举定义所有状态和事件。所有状态变更入口都走同一个服务方法方法内部先校验状态机规则合法则更新状态并记录一条状态流转日志异法立即返回错误。状态流转日志表虽然写入量增加了但特别有价值万一出现纠纷可以通过日志表还原整个订单生命周期同时它也是后续数据分析、异常诊断的重要依据。状态机的定义需要业务尽调和开发人员一起做每个分支都要确认尤其退款、异常单这种分支最容易在规则上遗漏。-- 订单状态流转日志表设计示例 CREATE TABLE order_status_log ( id BIGINT AUTO_INCREMENT PRIMARY KEY, order_id BIGINT NOT NULL COMMENT 订单ID, from_status TINYINT NOT NULL COMMENT 变更前状态, to_status TINYINT NOT NULL COMMENT 变更后状态, operator_type TINYINT NOT NULL COMMENT 操作人类型1用户2商户3系统4骑手5客服, operator_id VARCHAR(32) DEFAULT NULL COMMENT 操作人ID, created_at DATETIME NOT NULL COMMENT 变更时间, INDEX idx_order_status (order_id, created_at) ) COMMENT 订单状态流转日志表;这个表看起来很简单但实际价值很大后面排查线上问题时很多棘手的订单异常都是靠它定位的。所以我的建议是状态机相关的日志表一定不要省哪怕是早期想要快速上线也应该用最简单的记录方式先存下来。3.3 智能派单与骑手轨迹追踪调度系统的搭建智能派单系统是这个项目里技术难度最大、也是运营效果最直观的模块。我们的实现分两个阶段。第一阶段是“静态规则阶段”骑手位置每5秒上报一次到定位服务定位服务将位置写入Redis并保留最近50个轨迹点用于分析。订单被用户支付后调度服务的派单引擎启动它对所有空闲或负载低的骑手做一次筛选排除掉距离过远、即将超时的骑手然后对剩余骑手做综合评分。评分的权重是我们根据历史数据调出来的距离权重最高其次是预计出餐时间、骑手顺路程度、当前订单量。综合评分最高的骑手作为目标骑手系统下发派单任务。这个阶段我们踩过一个比较大的坑单纯按“当前距离最近”派单会导致某些热门商圈骑手扎堆而偏远区域骑手空置。后来我们在评分模型里加入了“骑手之间负载均衡”的指标每个骑手身上有一个“紧急度系数”订单越多紧急度系数越高评分时要对这样的骑手打折扣。这样系统会倾向于把订单派给相对空闲的骑手而不是让某个最顺路的骑手忙死。上线之后骑手满意度显著提升拒单率也降下来了。第二阶段是“动态策略阶段”。我们接入实时路况信息把路段的平均速度作为路径规划的一个输入这需要接入第三方地图服务。同时我们收集了大量订单的出餐时长数据训练了一个简易的出餐时间预测模型预测模型会结合商户历史出餐速度、当前时段、下单商品数量做估算。出餐时间预测不准是整个调度链路里最影响用户感知的环节如果预测时间过短骑手到了商户还要等很久配送自然超时如果预测时间过长又会让用户等待预估时间太长影响下单意愿。我们的解决方案是设置了一个动态安全缓冲系统在给用户展示预计送达时间时会基于预定时间加上出餐置信区间再做一次修正让用户看到的预估时间既有说服力又不至于太离谱。骑手轨迹追踪的实现细节也比较多。骑手位置不是实时全量写入数据库的因为高频写库会把数据库拖垮。我们的方案是骑手APP上报位置到定位服务定位服务把位置数据写入Redis并设置较短的过期时间用于实时页面展示同时每隔一段时间将压缩后的轨迹点批量写入消息队列消费者异步落库用于后续的里程统计和路径回放。轨迹压缩算法用了过滤掉冗余点的简单DP压缩降采样率之后轨迹精度损失很小但落库数据量减少了80%以上效果很显著。3.4 商户端与用户端的“E”化改造亮点商户端这次升级的核心是“经营数据看板”和“自助化操作”。做这个模块最大的难点不是数据计算而是要让不懂技术的人看得懂数据。我们接入了订单中心的实时数据流通过消息队列计算每个商户的今日成交额、订单量、热卖菜品排名、顾客复购率、退款率等指标。这些指标会实时渲染到商户端看板的页面上。数据指标不是只展示数字我们加了一个“对比上周同期”的涨跌幅标注商户一眼就能看出今天生意是变好了还是变差了。这个环节对商户留存的作用非常大很多商户反馈说“现在打开后台能看明白自己店里发生了什么”。用户端这边重点做了会员体系和个性化推荐。会员体系的基础是用户标签系统我们通过埋点采集用户的下单偏好、常驻位置、消费档次、高峰时段等信息利用离线任务给用户打上标签标签存储在用户画像服务里。推荐系统根据这些标签向用户展示“猜你喜欢”的菜品和店铺。这一块我们没有一开始就用复杂的深度学习模型而是先用简单的协同过滤加标签匹配效果已经比原来的“全部推荐一模一样的固定商品”好很多。个性化推荐对复购率有实际帮助在上线一个月后用户复购率提升了约15%数据还是靠对比实验得出的。另外用户端做了一层轻量级的“实时订单动态”展示。之前用户下单以后要手动刷新页面才能看到订单状态变化这次改造后通过WebSocket长连接把订单状态、骑手位置和预计送达时间实时推送到用户端页面。这个功能对体验的提升立竿见影用户不再焦虑“到底有没有人接单”。但实时推送在高峰期对网关和推送服务的压力很大这里用了消息队列做削峰每个用户的更新事件不是直接推送给客户端而是先存入用户各自的待推送队列再由推送服务按优先级拉去发送从而避免高并发时直接冲击连接层。4. 落地过程中的常见问题与排查技巧实录这个项目从启动到稳定运行中间踩过很多坑。我挑几个最有代表性的问题出来讲讲包括问题现象、定位过程、最终解决方案。这部分内容都是真金白银的实战经验优先级个人认为比前面的设计还高因为等你遇到同样问题时这些经验能帮你少走几周的弯路。4.1 库存扣减并发问题和订单超时导致的库存回补异常库存超卖这个问题我们最早在压测阶段就碰到了。当时用并发工具模拟了100个用户同时下单购买同一件商品结果订单创建成功了80个但库存实际只有50件这意味着有30个订单是超卖的。问题出在最开始的设计上先查询库存数量数量够的话再执行扣减这个“查询扣减”的操作不是原子的高并发下两个请求同时读到库存剩余1然后都执行扣减库存就变成了-1。解决方案就是用Redis的Lua脚本做原子扣减这是前面提到过的方案。脚本里先用GET拿到当前库存判断是否大于0大于0才执行DECR否则返回库存不足。Redis的Lua脚本是原子执行的不会存在并发穿插执行的问题所以扣减操作实际上是被串行化的。不过这里又引出第二个问题订单取消后库存回补不及时。我们最初的实现是取消订单后直接修改数据库库存和Redis里存储的库存数字可能不一致导致有时候显示“有库存”但实际下单失败。最终的方案是库存数据以Redis为主数据库只做流水记录。每次扣减和回补都记录一条库存流水异步把流水同步到数据库数据库库存表的值是最终修正后的结果用于每日对账。日常的高频判断和扣减走Redis可靠性极高效率也高。到了每天结算时点系统会根据库存流水重新计算一次Redis和数据库的差值发现差异自动修正这样两个数据源就能长期保持一致。4.2 支付回调重复通知与订单状态不一致支付通道的异步回调在生产环境经常会重复通知。有些第三方支付通道在收到“成功”应答之后还会隔一段时间再发一次通知如果我们的接口处理逻辑不幂等就会导致订单状态被重复更新甚至触发两次发货或两次结算。我们一开始就听说要在回调里做幂等但第一次上线还是出了问题支付成功后用户收到两份确认消息而且订单完成时间被更新成第二次回调的时间导致后续统计出现偏差。排查过程是这样的我们查询支付流水表发现同一笔支付流水出现了两条记录说明回调处理逻辑中没有先判断流水是否已经存在。修复方式是给支付流水表加了唯一业务流水号索引处理回调时先按流水号查库如果已存在且状态为成功直接返回“已处理”不再执行后续更新。同时订单更新操作也增加了状态条件只允许“待支付”状态更新为“已支付”如果订单已经是“已支付”状态更新请求直接忽略。这样才能从两个层面保证幂等性。这里特别提醒一点幂等设计不能只靠“数据库判断是否存在”一定要和状态条件更新结合起来双保险才可靠。4.3 骑手位置漂移导致调度误判骑手GPS上报的位置有时候会漂移特别是楼层密集的商圈和高架桥附近定位点会突然跳到几百米开外。如果调度系统直接拿漂移后的位置计算距离就会把订单派给实际相距很远的骑手造成严重的配送超时。这个问题在第一版调度系统上线后不久就暴露了线上客诉出现了一个明显的小高峰。我们的解决思路是增加位置修正环节骑手位置数据在进入调度计算前先经过一个卡尔曼滤波处理。这个滤波器会根据骑手前一时刻的位置、速度和上报频率预测当前位置然后把GPS上报的实际观测值按权重融合输出一个修正后的位置。滤波可以有效滤除跳变的漂移点对正常移动的轨迹影响很小。同时在调度评分时不使用单点位置而是取最近三个修正位置的平滑轨迹计算骑手与订单取餐点的道路距离进一步减少偶发漂移的影响。位置数据修正看起来是个很小的点但它对调度系统的影响是决定性的。如果你也在做类似业务我的建议是不要依赖原始GPS数据直接驱动业务判断至少加一层简单滤波哪怕只是一个“超过设定速度就忽略”的规则也能挡住大量明显错误的定位点。4.4 消息积压导致商户收不到新订单提醒在某个活动日商户端突然有大量订单没有收到新订单语音提醒导致商户无法及时接单用户侧看到商户长时间不对订单做确认客诉集中爆发。我们第一反应是检查推送服务结果发现RocketMQ的某个消费组积压了大量消息消费者线程处理速度跟不上生产速度。定位过程比较曲折。第一层原因很快查清活动日订单量暴增但商户端推送服务依赖的外部短信和语音服务有QPS限制导致消费速度被卡住。第二层原因是消费逻辑里同步调用外部通道时没有做超时控制和降级一旦外部服务变慢消费者线程就一直阻塞在等待响应上整个消费组越积越多。到达一定程度后RocketMQ会对消费滞后的队列做限流新的订单消息就会被暂时拒收形成恶性循环。这次的修复措施是典型的削峰填谷方案商户端的通知逻辑改造为两层队列。第一层是RocketMQ的订单消息消费者收到消息后先写入本地内存队列或Redis列表立即返回成功给Broker不等待外部通道响应。第二层是一个独立的异步推送Worker从Redis列表里拉取消息控制并发速率向外部通道发送失败的消息进入重试队列重试几次还失败就进入死信队列等待人工处理。这样就把“需要等待外部通道”的慢操作剥离出消息消费主链路消费者速度完全跟得上生产速度积压问题就解决了。同时我们也优化了外部通道的调用策略设置明确的超时时间和服务降级开关一旦外部通道响应超时就切换到备用通道或者暂时降级为站内信通知。5. 项目验收与经验沉淀系统上线稳定运行了一段时间后我们对整个项目做了验收复盘。从数据上看改造后的系统在高峰期可以稳定支撑的订单量是改造前的三倍以上接口平均响应时间降低了约60%配送超时率下降超过40%骑手人均单量提升了约18%商户端日活跃率也明显上升。这些数字对团队是比较大的正反馈证明当初在架构、调度、生态三个方向的投入都是值得的。这里也想分享一个对这类系统级升级项目的个人判断。很多人会问“为什么你们不直接上最先进的架构方案”我的观点是架构方案的选择永远要匹配团队当前的业务阶段和运维能力。我们第一版也讨论过要上完整的分布式链路追踪、要上算法平台但最终都按“最小可落地”的原则分批落地。技术方案的价值不在于新而在于能稳定跑起来解决实际问题。一个能用起来的简单规则远比一个跑不起来的复杂模型有价值。如果后续要继续扩展我觉得开放平台的深度运营是下一个重点。目前我们已经接入了第三方配送运力但商户自助化的营销工具、供应链协同、金融结算服务还比较薄。把这些生态能力做深外卖系统才能真正从“工具”进化为“平台”。当然这些都要建立在核心链路足够稳定的基础上步子不能迈得太大。这个项目的经验总结下来就一句话先让核心链路跑稳再做智能化提效最后才是开放生态次序不能乱。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑