分布式系统

至少一次投递下的去重:窗口、墓碑与业务唯一性

比较内存缓存、持久去重表、业务唯一约束和时间窗口,设计重复事件处理、过期策略与删除后迟到消息的墓碑机制。

一项能力能否长期维护,不取决于演示是否成功,而取决于团队能否解释每个状态、每次重试和每一份残留数据。 技术 eventId 能识别同一次投递,业务键能识别不同事件表达的同一效果。两者配合才能防止发布方重建事件 ID 后再次执行相同副作用。

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

设计时必须回答的问题

落地时要把关键选择变成稳定契约:输入如何校验、状态由谁推进、资源何时释放、旧版本如何降级。只有这样,后续优化才不会改变原有语义。

  • 在消费事务中先插入 eventId 唯一行再执行状态变更;不可重复副作用另有 businessKey 唯一约束,删除实体保留有限期墓碑。
  • 为状态写出唯一所有者、版本号和终态;任何回调只能修改自己创建的版本。
  • 资源释放是协议的一部分:定时器、句柄、队列和临时数据都要在终态中可重复清理。

“至少一次投递下的去重:窗口、墓碑与业务唯一性”的交付标准是正常路径可用、异常路径收敛、资源有界,并且用户能理解系统为何采用当前状态。 这样得到的不是演示代码,而是能解释、能降级、能回滚的生产能力。

边界情况不是附加项

最值得优先排查的是会静默留下错误事实的故障:界面看似恢复,底层队列、权限或计数却已分叉。这类问题通常在下一次动作才暴露。

  • TTL 小于消息最大滞留期会让旧重复重新生效;只在 Redis 缓存去重则在驱逐、故障转移或冷启动后失去历史。
  • 旧响应在新任务建立后迟到,如果没有版本隔离,会把健康状态覆盖成失败或再次启动已取消工作。
  • 指标标签直接包含用户或任务标识,既制造高基数成本,也让诊断数据泄露不必要的身份信息。

用证据确认它真的可用

验证时同时观察两端状态、持久化记录和可观测指标。单看某个按钮或一次接口响应,无法证明整个闭环成立。

  1. 发送相同 eventId、不同 eventId 同业务键和超过正常延迟的旧删除事件,验证结果、审计与存储清理都符合策略。
  2. 让刷新、取消、超时和远端完成在同一调度窗口发生,断言系统只产生一个终态和一次副作用。
  3. 发布前记录成功率、p50/p95/p99 延迟、错误分类和资源高水位,并为回退条件设定明确阈值。

最终结果应同时满足正确性、可恢复性和可解释性。任何一项只能依赖刷新页面或工程师猜测,都说明协议闭环仍不完整。

把方法变成一次真实连接

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

开始免费使用