报告 008 · 接纳、启动与核对入账
日期:2026-09-19。证据为真实子进程、管道和本地 SQLite 事务,不是 PostgreSQL、网络或 Kubernetes 验证。方案归纳见恢复决策。
1. 条件和过程
先固定 15 个预登记场景,再执行独立脚本。provider 数据库保存接纳、可派发状态和启动进入记录,world 独立保存效果,authority 保存指派、证据、预留、额度、释放账与 outbox;三库之间没有事务。均使用 SQLite 3.53.4 WAL/FULL,Python 3.14.7。
父进程是受控运行环境,响应派发子进程的启动请求并创建独立工作进程。因此杀掉派发器不会自动杀掉工作者。所有次序由管道屏障控制,只杀本实验子进程;不把等待时长当作节点停止证据。实验未连接外部数据库或服务。
首次执行遇到记录器位置参数 name 与观测字段 name= 冲突,8 例中断。首次结果和原脚本完整保留,不用于完整结论。仅修复参数命名后,脚本修订 v2 全例通过。
复核 v2 发现 B2 在新工作完成后才放行旧工作,代号变化与状态变化同时影响拒绝。v3 将旧请求放在换代后、新执行者进入前,此时仍为 queued,以区分代号检查的贡献;预登记场景、SQL 和判据不变。修订记录说明差异,v2 脚本和数据仍保留。下表只统计 v3 完整运行,不把重跑合并为更多独立样本。
2. 结果
15 例、26 个子进程、10 次 SIGKILL、156 项断言,错误 0。 断言包含进程退出与屏障,不能解释为 156 个独立故障场景。未测吞吐、时延或线上发生概率。
| 场景 | 实测观察 | 方案含义 |
|---|---|---|
| A1 提交前确认 | 确认已发,进程被杀后接纳记录 0,效果 0 | 确认须在接纳事务完成后发送 |
| A2 只依赖内存待办 | 接纳存在,恢复分支无可派发项,效果 0 | 接纳必须定义可恢复的派发责任,通知不能是唯一入口 |
| A3 共同持久化并扫描 | 恢复原键,效果 1 | 持久待办+重扫能在该窗口继续推进 |
| B1 启动后再登记 | 派发器退出,原工作存活;盲重启累计效果 2 | 进程创建与启动回执间存在歧义 |
| B2 换代后旧执行者进入 | queued、代号 2 时拒绝旧代号 1;新执行者效果 1 | 在产生效果前检查当前启动代号 |
| B3 同代号重复启动 | 两个进程竞争,一个 entered、一个拒绝,效果 1 | 代号相等还需一次性条件进入 |
| B4/B5 entered 后终止 | provider 记录相同,实际效果 0/1;均不自动重放 | 进入记录不能证明效果;保守 unknown 是代价 |
| C1 返还额度与释放账分离 | 额度初始 0,重试后成为 2,释放账和 outbox 各 1 | 只有消息/回执去重不足以保证额度守恒 |
| C2 原子事务提交前被杀 | 事务回滚,恢复重试后额度 1,账及 outbox 各 1 | 释放、额度与回执须一起提交 |
| C3 提交后回执前被杀 | 重试识别已释放,额度仍 1 | 响应丢失不重复返还 |
| C4 两个证据 ID 并发入账 | 同一预留只有一次释放,额度 1、outbox 1 | 结算按 ReservationID 去重,不能只按 ProofID |
| D1 只匹配资源名 | 旧执行者的证据错误释放了新预留 | 资源名不是一次占用的身份 |
| D2 完整身份关联 | 拒绝旧预留/旧执行者/旧资源实例的证据,新预留仍 held | 证据范围必须对应具体预留 |
| D3 接管后旧事实到达 | 旧 owner 入账被拒,事实保留,新 owner 释放一次 | 历史事实接入与当前状态写权分开 |
A2 不是证明接纳记录无法恢复:若 queued 本身已定义为可扫描待办,就不需要额外 pending 表。本例反对的是仅凭内存唤醒推进、恢复时不扫描持久派发责任;A3 可以用状态行或 outbox 实现该责任。
3. 明确的协议基线
- 接纳后确认。 业务键、参数与可派发责任原子落库,完成后确认;通知可重复、可丢失,启动与重连主动扫描持久状态。
- 重复启动受控。 对可控制执行入口的提供者,启动令牌绑定业务键和 StartEpoch;执行者在效果前条件转为 entered。未进入可条件换代,已进入的非原子动作无可靠证据时不重放。
- 按预留一次性入账。 可信停止证据先保存;当前 owner 在一个事务内核对指派和证据范围,完成预留释放、额度返还、唯一释放账及 outbox。
- 保留旧事实。 旧来源证据不因接管而丢弃,但它不能授予旧 owner 当前入账权。
选择这些作为下一阶段设计和实验基线;具体持久化实现仍需数据库与集群验收。独立消息系统或工作流引擎不能替代提供者进入契约和外部效果核对,见官方资料与后端选择。
4. 条件与剩余边界
进入检查必须覆盖所有实际效果路径,并与换代操作竞争同一权威状态;不能把只在调度器端校验视为等价。B4/B5 说明它提供的是保守的重放边界,不是非原子效果恰好一次。对第三方平台不能凭空加上这项能力;使用其原生幂等/查询契约,否则保持 unknown。
SQLite 写事务串行化不证明 PostgreSQL 并发隔离或复制行为。证据认证、持久储存回退、跨资源事务、长动作、外部设备已经释放的真实性均为未测范围。C/D 使用可信停止证据的固定输入,验证的是入账和关联;D2 同时改变多个身份字段,不是逐字段必要性的独立消融。
每组次序是有限对照,不是穷尽调度。后续须验证接纳取消与进入同时竞争、旧备份恢复导致的代号回退,以及数据库多写入者/故障转移下的相同不变量。
当前命令:python3 experiments/dispatch-settlement/experiment.py --output experiments/results/dispatch-settlement-v3.json。复跑换路径,程序拒绝覆盖。临时库已清理,逐事件轨迹与各库终态表保存在 JSON。
| 材料 | SHA-256 |
|---|---|
| 预登记 README.md | 0da558aad135bae764435934636d6a6b8e2824a53213d43c50993c9149e3070e |
| 当前 experiment.py | 4339a9dfb8a984a3cd8001a491ca0b4f31e974fdf2b9f0a2dbebb99ae66598bf |
| dispatch-settlement-v3.json | c278650caa61f848a037510d30cfbd2d890d4fa8ec0d5f726892a25e0355c3a0 |
初版和 v2 脚本哈希见修订记录,各次 JSON 也记录其脚本与预登记哈希。旧 E0~E8c 的材料保持不变。
数据可用性
本报告公开实验条件、汇总统计和失败分析。原始输入、脚本及逐次运行记录未随报告发布,因此不能仅凭本文独立复现实验。