分布式系统

超时为什么要用单调时钟:墙上时间会跳

区分持续时间与日历时间,处理 NTP 校时、休眠恢复、时区变化和跨进程截止时间,避免超时提前、延后或变成负数。

工程上最危险的不是完全不可用,而是在理想环境里正常、进入真实网络和真实数据量后悄悄失去边界。 进程内耗时应由 monotonic clock 计算,因为它不随系统校时倒退;跨机器传递的是服务端签发的绝对截止时间和允许偏差,接收方重新计算本地预算。

分布式正确性来自幂等键、租约、单调版本和可对账事实,而不是假设请求只到一次。超时代表结果未知,调用方不能未经确认就把它解释成失败。

工程边界与取舍

这项能力横跨客户端、网络与服务端,局部最优很容易制造全局故障。工程决策需要同时约束两端行为、持久化事实和运维预算。

  • API 类型区分 Instant、Duration 与 WallTimestamp,禁止把 Date.now 差值用于重试预算;休眠恢复后按剩余截止时间重新调度。
  • 先定义正常、降级、取消和失败四类终态,再让界面、存储与指标消费同一状态。
  • 兼容性通过显式能力协商决定,旧客户端得到可解释的降级路径,而不是进入半可用状态。

“超时为什么要用单调时钟:墙上时间会跳”的交付标准是正常路径可用、异常路径收敛、资源有界,并且用户能理解系统为何采用当前状态。 这样得到的不是演示代码,而是能解释、能降级、能回滚的生产能力。

生产环境会怎样出错

失败路径需要与成功路径共享同一套状态模型。只弹一个错误提示却不释放资源、不传播终态,下一次恢复就会继承脏状态。

  • NTP 把时钟向后调时,基于墙钟的锁持有时间突然增加;向前跳则让所有租约在同一刻提前过期。
  • 失败被压成一个布尔值,调用方无法区分可重试、需用户介入与永久拒绝,最终形成无限循环。
  • 指标标签直接包含用户或任务标识,既制造高基数成本,也让诊断数据泄露不必要的身份信息。

把测试跑成闭环

测试不能以“最后成功了”结束。还要测量经历了多少次副作用、等待多久、是否泄露内容,以及失败后再次执行能否从干净基线开始。

  1. 在测试时钟中注入前跳、后跳、休眠两小时和时区改变,断言持续时间逻辑只受单调推进影响且跨服务截止时间保守收敛。
  2. 让刷新、取消、超时和远端完成在同一调度窗口发生,断言系统只产生一个终态和一次副作用。
  3. 发布前记录成功率、p50/p95/p99 延迟、错误分类和资源高水位,并为回退条件设定明确阈值。

当实现能够安全降级、重复执行不产生额外副作用、故障指标早于投诉出现时,这项能力才算具备长期维护价值。

把方法变成一次真实连接

打开 uCopy,让两台设备在浏览器里安全连接并开始传输。

开始免费使用