编码、架构与项目 · KNOWLEDGE CHAPTER
K30

数据同步与恢复

网络会把“服务端是否完成”与“客户端是否知道”分开。同步系统因此需要稳定操作身份、明确确认点和可恢复日志:请求失败不代表业务没发生,进度100%也不代表已提交,恢复必须先对账再继续。

编码、架构与项目2 道章节练习4 道主练关联

核心模型

网络会把“服务端是否完成”与“客户端是否知道”分开。同步系统因此需要稳定操作身份、明确确认点和可恢复日志:请求失败不代表业务没发生,进度100%也不代表已提交,恢复必须先对账再继续。

原理与机制

上传进度不是提交证明

大文件按 Blob 范围切片,以上传会话、分片编号和内容校验约定身份,受控并发避免同时读完整文件。重连查询服务端已确认分片,只补缺失部分;总体进度按唯一字节加权,不把重试重复累计。XHR upload progress 描述传输过程,之后还有校验、合并和持久化。完成接口需要原子记录会话结果,响应丢失后重放同一键返回原结果。授权、限额、真实内容检查和安全文件名属于服务端,哈希匹配也不能替代恶意内容检查。

自动保存维护三份时间线

当前草稿、已确认基线、发送中的快照必须分开。发出 V1 后用户又编辑成 V2,V1 成功只推进基线,不能覆盖 V2 或把全部草稿标成已保存。后续请求合并或串行,并带新基线版本。服务端用强 ETag/If-Match 或等价版本做原子条件更新,版本冲突返回412等明确结果;共同基线、远端和本地三方合并,无法安全合并就让用户决策。客户端时钟和防抖都不能代替原子比较。

离线队列记录意图与确认

草稿保证可继续编辑,outbox 则记录待执行操作;每项有稳定 ID、账号作用域、资源版本、载荷与状态。本地事务完成后才显示本地已保存,服务端确认后才显示同步完成。提交成功但响应丢失时,同一用户作用域内的幂等键防重复;依赖操作串行,独立操作可受控并发。退出或切账号时不能把旧队列借新身份发送;撤权、冲突与永久业务错误应进入显式状态,而非无限重放。

本地持久化也需要恢复协议

IndexedDB 在无待处理请求且当前活动阶段未再放入请求时可自动提交,不能开事务后等待网络再回来写。它与 OPFS 不是同一个原子事务:可以先写临时文件,再提交带状态的元数据,启动时对账孤立文件和缺文件记录。配额、站点清理与设备故障意味着本地保存不是永不丢失,需区分可重建缓存与必须导出的原始资料。后台同步或 service worker 只改善机会,页面重开仍要主动恢复队列。

实时传输靠游标恢复业务连续性

选择轮询、SSE 或 WebSocket 先看单向/双向、延迟和基础设施。连接内有序不代表跨重连无丢失,事件 ID、已确认游标与去重集合才支撑补拉;超出保留窗口需取新快照,未读数由服务端权威计算。重连使用有上限的退避与抖动,鉴权失败停止盲试;慢消费者有队列上限、合并渲染和降级。多标签共享连接增加选主、租约与短时双主处理,BroadcastChannel 自身不提供互斥。

最小示例

javascript
javascript
// 纯状态示例:确认旧发送不覆盖新草稿
function acknowledge(state, sent, newVersion) {
  return {
    ...state,
    base: sent.text,
    baseVersion: newVersion,
    dirty: state.draft !== sent.text
  };
}
const state = { base: 'A', baseVersion: 1, draft: 'C' };
const sent = { text: 'B', baseVersion: 1 };
console.log(acknowledge(state, sent, 2));

结果 base=B、版本2,但 draft 仍为C、dirty=true。这里约定一次只有一个在途保存,并以文本相等判断是否脏;丰富文档应改用编辑修订号或内容契约。服务端仍需独立原子校验 sent.baseVersion,纯函数无法防远端覆盖。

核验:Node v24.19.0:旧保存确认保留新草稿、推进基线、保持dirty及输入不变断言通过;不覆盖服务端条件写入或存储事务。

边界与取舍

边界

  • navigator.onLine 为真只表明浏览器的连接判断,不能证明目标服务可达,更不能证明队列已确认。
  • “服务端成功、响应丢失”必须纳入测试;新建幂等键后重试会把同一意图当成新操作。
  • 离线删除遇到远端修改属于业务冲突;CRDT、WebSocket 或重试都不会替你决定哪方应赢。

取舍

  • 保留操作日志便于恢复与审计,却增加存储和隐私成本;按业务保留窗口压缩并保护敏感队列。
  • 串行保存容易维护基线,吞吐较低;并发需明确独立性、顺序和提交条件,不能只增加并发数。

口述示范

我会把传输、暂存和确认分开,用操作 ID 防重复、版本防覆盖、日志与游标补缺口。每个恢复动作都先核对账号与服务端事实,并把冲突、失败和本地已保存清楚展示。

章节练习

练习 1

分片合并在服务端成功,但浏览器超时后重试,怎样证明不会多建一份文件?

展开检查点
  • 会话与幂等键绑定同一载荷及用户,服务端原子记录完成结果。
  • 查询确认状态,进度按唯一字节累计,测试丢响应和重复完成。
练习 2

假设 TranslateFlow 用 OPFS 存文件、IndexedDB 存元数据,设计两种半成功的恢复。

展开检查点
  • 临时文件、元数据状态和启动对账;两存储不在同一事务。
  • 处理文件有记录无、记录有文件无,演练配额满及账号切换;说明导出入口。

参考来源与核验边界

2026-10-04 核验;后台同步、OPFS 与持久化策略需按浏览器支持和配额实测。TranslateFlow 仅为假设设计练习,未声称已有跨存储实现。

内容版本:2026-10-04.2 · 题目和来源 ID 保持原样,本站不将面经标签解释为企业官方出题或高频保证。