跳转至

架构对比:日志驱动链路 vs 重客户端直写

日期:2026-09-01;修订:2026-09-26(现行侧改为 180 秒实测、历史分层 ADR-0018、服务数) 两侧详情:arch_20260901_current_log_driven_summary.md(现行)、 arch_20260901_direct_write_proposal.md(提案)。 结论先行:两者有按落点合并、确定性幂等和 ACK 不等末端投递等可复用原则,但提案的 提交恢复、群任务恢复、会话权威/未读、成员快照和保留期后恢复仍为 P0 未决。 因此尚不能称“高度同构”或“只剩两条真实分歧”。

1. 逐维对比

维度 现行(日志驱动) 提案(直写)
单聊链路跳数 gateway → writer → Outbox → fanout → dispatch → mailbox(两跳日志) 目标是 gateway → 会话节点;是否仍需外部任务介质取决于 P0 决策
单聊 ACK 谓词 COMMITTED(正文 + 可靠 Outbox 持久) 目标为 CommitIntent=COMPLETE,且正文与 A/B 用户存储均 durable、可读;未实现
群聊 ACK 谓词 COMMITTED(正文 + 冻结成员版本的 Outbox 事实);异步展开可重放 目标为正文 + GroupCommitIntent + 冻结快照引用 + 全部目标任务可恢复;当前未定义,不能以“仅正文持久”ACK
ACK 前故障恢复 CommitIntent/持久 dedup 固化坐标后续做,Outbox/日志恢复后续阶段 双写跨记录不原子;必须由 CommitIntent、可见性门和恢复者续做,当前未实现
ACK 延迟构成 1 次 Redis 融合 Lua(幂等 + 序号 + 热层历史)+ 1 次日志发布 + 1 次 Lua(COMMITTED);10k msg/s 实测 P50 8 / P99 17 ms 至少包含 CommitIntent、历史、两份用户写和可见性确认;实际时延未知
端到端延迟 ACK 之后再约 65 ms(P50,10k msg/s):fanout 批周期约 30 ms + mailbox 物化 + 推送;端到端 P50/P99 73/108 ms,180 秒实测 可能更低;零实现零实测,旧 TCP 数据不可作背书
历史持久化 分层(ADR-0018):Redis 7 天热窗口同步提交,HistoryArchiver 消费 Outbox 异步批量归档 ScyllaDB,裁剪只在归档水位覆盖后 目标为"近 7 天用户存储",7 天之后的权威、下界与拼接协议未定义
投递修复源 日志重放,不依赖客户端在场 单聊 ACK 前/后恢复者均须依赖 CommitIntent;群聊 ACK 后任务恢复源尚未定义
排序 conversation_seq(严格递增,允许空洞) 时间戳、conversation_seq 或服务端覆盖证明均未定;HLC 不是会话全序或增量下界
同步完整性 锚点是 MAILBOX_BATCH.covered_through_seq、lane W 与 CURSOR_*/REBUILD;conversation_seq、mailbox_seq 均可稀疏,禁止以差值判缺口 7 天内外的游标、覆盖证明、CURSOR_* 与 REBUILD 均未定义;时间戳下界存在永久漏消息风险
幂等 (tenant,sender,client_message_id) 持久 dedup 固化坐标 + 下游 dispatch_id 收敛 同一键写可用存储主键收敛;首次坐标和 ACK 丢失重试仍须 (tenant,sender,client_message_id) CommitIntent,不能宣称零 dedup 事实
fencing epoch/租约体系 未证明可免;除非所有正确性状态由带 epoch/CAS 的线性化存储处理且数据面拒绝旧 owner,否则须保留等价 fencing
群聊展开 按 MailboxShard 合并 GroupDispatch,冻结快照和进度持久 按用户落点合并的算法相似;快照、任务、进度、恢复者与保留期均未解
会话列表/未读 qsession 的 durable projection 消费已实现;UserConversationState 会话集合兜底(ADR-0021)已实现,越窗期间首次出现且之后无消息的会话仍无法恢复 持久权威、输入流和重建算法未解;不能用第三份同步写或尽力通知替代
审计/多消费者 天然支持 取决于候选介质是否经能力矩阵证明独立 checkpoint、重放和隔离;内存队列不具备
削峰 broker 兜住突发 是否有可恢复缓冲未定;无外部介质时反压直达客户端
弹性 确定映射、状态搬迁及分区数冻结均有成本;目标 lane 独立推进当前也未实现,慢 record 仍阻塞同 shard targetId 映射、CommitIntent/任务/用户状态迁移同样需要设计,不能把现行自伤误算成日志介质固有限制
运维面 6 服务(含 archiver)+ 多 Redis + Redpanda + ScyllaDB 三节点 可能少 broker/fanout,但增加提交恢复、可见性门与迁移责任;净复杂度未实证
实证 开发机 180 秒 + T-HEAVY:10k 连续 3/3、15k 连续 3/3、分层形态 10k 通过;功能 smoke 15/15。仍非目标硬件容量结论,混沌与 orphan 审计未做 零实现零实测;不得引用历史 TCP 数字作方案性能或可靠性证据

2. 已出现的共同原则,不等于实现同构

讨论显示两侧可能复用下列原则:服务端生成坐标、客户端持久 pending、按落点合并、确定性任务/条目 幂等、LRU 只作缓存、ACK 不表示已送达或已读。这些是设计约束,不是完成的等价证明。

2026-09-26 起,提案的「近 7 天热数据 + 之后归档」已被现行侧以 ADR-0018 吸收(提交热路径 只写 Redis,历史异步归档 ScyllaDB)。这缩小了两侧在「每条消息同步写库」上的差距,但不改变 下列仍待提案实现的项。

提案若要吸收现行的可靠性,仍须明确实现:

  • (tenant, sender, client_message_id) 的 CommitIntent 和规范坐标固化;
  • 跨历史/用户存储双写的恢复者与 ACK 可见性门;
  • 群的冻结成员快照、可恢复任务、进度、重放保留和旧 owner 处理;
  • 会话集合、已读/未读、控制事件和 7 天后 REBUILD 的持久权威。

现行可评估将投递介质继续抽象,但不能由 trait 存在推出 Redis Stream 或 WAL 已具备相同故障语义。

3. 尚未收敛的决策轴

以下至少六轴彼此相关,但不能压缩为两项:

  1. 提交原子性、ACK 与恢复:CommitIntent 的内容、坐标分配、双写/任务接收的恢复和可见性门。
  2. 群任务可靠性:发送时成员快照、任务 ID、进度提交顺序、重放/GC、ACK 后独立恢复者。
  3. 会话状态与保留期恢复:会话集合、已读/未读、控制事件、7 天后游标和 REBUILD 的权威源。
  4. 排序与完整性协议:conversation_seq、HLC、服务端覆盖证明和客户端本地验证可组合,不能表述为 “seq vs 时间戳不可兼得”;选择及成本需单独 ADR。
  5. 投递介质的能力边界:内存、Redis Stream、本地 WAL、Redpanda 分别在节点丢失、复制、确认、 保留、重放、多消费者与背压上验证,不能只按名称分档。
  6. 所有权与 fencing:扩缩容、网络分区、旧 owner 复活和数据面拒绝陈旧写入的机制。

上述 P0 闭合前,“直写”和“日志驱动”只是在若干局部算法上相似,不能据此作为路线收敛或 SLA 选择。

4. 决策指引(先满足前置条件)

若产品要求…… 当前判断
千人群 + 可重建会话列表 + 审计事实流 现行已有日志恢复域、qsession durable projection 与 UserConversationState 会话集合兜底(ADR-0021);提案还须先闭合 §3 的 P0
单聊/小群为主,追求更少部件或较低延迟 可做原型假设,但不能在 CommitIntent、7 天后恢复及故障矩阵前承诺 SLA
「消息不重不丢可恢复」按部署可选 先为每种介质完成能力矩阵;未验证介质不得承载 ACK 后任务
客户端不可控(第三方接入、弱终端) 现行更匹配;重客户端不能承担服务端提交/群恢复缺口

5. 建议的下一步(按依赖顺序)

  1. 先写 P0 ADR:分别冻结单聊 CommitIntent/ACK 恢复、群任务/成员快照恢复、会话权威/未读和 7 天后 REBUILD;每份 ADR 必须列崩溃、ACK 丢失、迁移和旧 owner 向量。
  2. 验证介质能力矩阵:对 Redis Stream、本地 WAL 与 Redpanda 运行节点重启/永久丢失、故障切换、 重复消费、保留到期、独立消费者和背压实验;失败者排除出 ACK 后任务介质。
  3. 再做单聊直写原型:与现行使用相同硬件、负载、持续时间、ACK 谓词、最终覆盖率和故障注入, 只报告实测结果;不得使用旧 TCP 数字替代。
  4. 并行修复共同弹性问题:会合哈希和搬迁工具可服务两侧,但不能替代 fencing/状态恢复设计。