题目重点:Phone Screen 题目问默认 Retryer 与自定义扩展;把执行、错误分类、重试上限、退避、取消与幂等拆成策略。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练接口 run(operation, policy, cancellation);operation 可能成功返回值或抛异常。
- 默认策略示意最多 3 次、只重试被分类为 transient 的错误、指数退避加 jitter;这不是题目给的默认值。
- 重试上限按总尝试次数而不是额外重试次数计,故最多 3 次=首次+两次重试;现场须确认。
解题路线
- 把 operation 执行与 shouldRetry(error,attempt)、delay(attempt,error)、onAttempt、deadline/cancel 等接口分离,使定制无需复制主循环。
- 循环每次先核取消/总 deadline,再执行 operation;成功立即返回。失败时先分类永久/暂时,再检查总尝试次数与剩余 deadline,满足才 sleep 退避;耗尽则原样抛出最后异常或包装可追踪错误。
- 退避使用有上界指数和随机抖动,避免同时失败的客户端同步重试;全局并发与服务端限流也要共同约束,不能靠 Retryer 自己解决雪崩。
- 对于创建订单等非幂等操作,必须有 idempotency key、状态查询或禁止自动重试;超时不等于对端未成功。
- 用可注入 clock/sleeper 和确定性随机源做测试,覆盖立即成功、暂时错误后成功、永久错误、上限耗尽、取消、deadline 与 sleep 边界。
手动走一遍
训练序列:一次 transient 失败、第二次成功时只调用两次,期间按 policy 延迟;如果第一次返回 timeout 但对端可能已创建记录,只有携带相同幂等键或查状态才可安全重试。具体重试次数非题目约束。
规模与取舍
最多 A 次尝试,时间为各次 operation 时长加退避之和,额外内存 O(1)(不计日志);指数退避可因 deadline 提前终止。
易错点与追问
容易失分的边界
- 捕获所有异常无限重试。
- 把最大重试次数与总尝试次数混淆。
- 失败后 sleep 再发现已超 deadline。
- 无 jitter 导致重试风暴。
- 超时后对非幂等写重发生成重复副作用。
继续深挖
- 如何注入自定义错误分类与退避?
- 服务端 429/Retry-After 如何处理?
- 如何在异步协程中支持取消?
- 重试与熔断/限流如何配合?
