☰
系统设计面画完主流程,再问一句失败后怎么办
2026/10/28 10:19:59 网站建设 项目流程

系统设计面里,主流程画通只完成了一部分。真正值得往下聊的是:某一步没返回时,你知不知道事情到底做成了没有。先把这个不确定性讲清楚,再谈要不要加重试、队列或缓存。

比如设计一个任务提交接口:请求进来,生成任务,交给执行方,最后返回任务编号。顺着箭头说一遍很容易。现在把响应丢掉:调用方超时了,任务却可能已经创建。用户再点一次,是找回原任务,还是多创建一份?

超时不是业务结果

超时说明调用方在规定时间内没拿到结果,不能单凭这一点判断服务端没处理。请求可能没送到,也可能处理了一半,还可能已经完成,只是响应没能回来。三个位置的故障表面相似,后续动作却可能不同。

因此先给操作分类。重复读取一份任务状态,与重复触发一项有副作用的任务,不应该直接套同一种策略。前者主要要考虑成本和时效,后者还要考虑重复执行会产生什么业务后果。这里的分类取决于具体操作,不取决于接口叫什么名字。

常见的追问是:那就加个唯一请求标识,可以吗?可以作为方案的一部分,但标识要回答完整:谁生成、代表哪一次业务意图、重试时是否复用、保存多久、同一标识带着不同参数怎么办。每次重试都生成新标识,服务端仍然无法把它们认成同一次提交。

把判重和创建之间的缝隙画出来

如果方案是「先查标识,不存在就创建」,再同时放进两个请求。它们有可能都查到不存在,然后各创建一份。口头说有去重,并没有解释并发时如何阻止重复。

接下来可以讨论唯一性约束、原子操作或事务,让判定与状态写入之间有明确保证。具体选什么要看存储能力和业务边界;面试里至少要指出依赖什么保证。单进程里的一把锁,不能自动约束其他实例也在做同一件事。

任务写入成功、投递给执行方失败,又是另一个缝隙。你可以先把任务状态可靠保存,再由后续机制继续投递,但这会引入等待、重复投递和恢复时机的问题。队列能改变工作分配方式,不会替你定义业务上「完成一次」的含义。

重试必须有停下来的地方

说「失败就重试」还不够。什么错误值得重试?最多试多久?每次之间等多长?超过预算以后由谁接手?参数本身不合法时,原样重复通常不能修好它;暂时不可达时,重试则可能有意义。

调用链上每层都各自重试,可能放大下游请求量。哪层负责重试、总体等待预算是多少,要放在一张时间线上看。没有负载和延迟信息,就不要报一个看起来专业的固定次数,只要说清如何根据预算和故障类型决定。

用户要看到哪一种中间状态

失败路径不只存在于服务之间。提交后暂时拿不到最终结果,界面是显示处理中、允许查询,还是直接报失败?如果显示失败却后台继续执行,用户再次提交就可能把技术上的不确定性变成重复业务操作。

设计里可以把「已接收」「执行中」「完成」「失败」分开,但每个状态要对应事实。已接收不等于已经执行成功,失败也需要说明还能不能重试。状态的命名并不能替代状态转换的条件。

最后沿着故障再走一遍:请求超时后怎么找回结果,进程重启后怎么恢复,重复到达后怎么识别。每经过一个节点,指出状态存在哪里、由谁推进、怎样发现长期没有进展。这样画出来的监控需求才有对象,而不只是一句「加日志和告警」。

面试时间不够时,可以少扩展一种组件,保留一条完整失败路径。沿它讲清可接受的重复、丢失和延迟,比把所有系统名词都摆上去更容易检验设计。

你的方案里,最难回答的是请求没到,还是事情做完了却没人知道?

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询