Skip to content

数据同步的难点

本文档记录蓝牙门锁数据同步方案的设计背景,解释为什么不采用"双向自动同步"的方案。

为什么不做双向自动同步?

理想中的方案:

  • 云端和设备都可以自由管理用户、凭证
  • APP 连接时自动双向同步,合并数据
  • 用户无感知,数据始终一致

这是一个经典的分布式系统难题,类似 MySQL 双主同步。

难点一:增量对比

要实现增量同步,需要知道"哪些数据变了"。

方案对比

方案实现方式问题
时间戳每条记录带 updated_at设备时钟可能不准;删除操作无法追踪
版本号每条记录带版本号只知道"有变更",不知道"改了什么"
变更日志记录每个增删改操作存储开销大,设备资源有限
全量对比拉取全量数据后对比无法区分"新增"和"删除"

删除操作的困境

假设云端有凭证 A、B、C,设备删除了 B:

云端:  A, B, C
设备:  A, C

APP 连接时对比发现"设备少了 B",但无法区分:

  • 场景1:设备删除了 B → 应该告诉云端删除 B
  • 场景2:云端新增了 B → 应该把 B 下发到设备

除非记录操作日志(binlog),否则无法区分这两种情况。

难点二:冲突解决

即使能检测出变更,双端同时修改时仍有冲突。

冲突场景

场景云端操作设备操作如何处理?
1删除用户 A修改用户 A 的名称删除 or 保留?
2修改密码为 1234修改密码为 5678用哪个?
3删除指纹 X给指纹 X 改名

常见解决策略

策略说明问题
时间戳优先最后修改的为准设备时钟不可靠
云端优先冲突时云端覆盖设备设备操作可能丢失
设备优先冲突时设备覆盖云端云端操作可能丢失
手动解决提示用户选择用户体验差

手动解决:

  1. 用户无法理解此类操作。
  2. 所有冲突类型都需要枚举出来以合适的方式供用户选择处理方案,实现成本高昂。

难点三:实现成本

要实现可靠的双向同步,需要:

组件说明成本
操作日志设备记录每个增删改操作存储空间、Flash 寿命
版本向量追踪每端的修改历史复杂的数据结构
冲突检测发现并处理冲突复杂的业务逻辑
回滚机制同步失败时恢复更多存储空间

这相当于在资源受限的嵌入式设备上实现一个分布式数据库同步系统。

对于门锁这种嵌入式设备,成本过高。

我们的方案

接受现实,简化设计:

方向策略说明
云端 → 设备云端优先,自动下发版本号对比,有变更则全量覆盖该类型数据
设备 → 云端手动触发,设备覆盖用户主动点击"同步数据"
事件记录设备产生,增量上报只增不改不删,用 ID 增量拉取

为什么这样设计

  1. 避免冲突:明确数据所有权,不存在"双方同时修改"的场景
  2. 简化实现:设备不需要记录操作日志,只维护版本号
  3. 用户可控:设备本地操作不会被意外覆盖,需要用户主动同步
  4. 资源友好:设备端实现简单,不消耗额外存储

用户需要理解

  • 云端管理的操作会自动生效
  • 设备本地操作需要手动同步到云端
  • 手动同步时,设备数据会覆盖云端

类比

这个方案类似于:

  • Git 的 force push:手动同步 = 设备 force push 到云端
  • MySQL 主从复制:云端是主库,设备是从库(但从库偶尔可写)
  • 备份恢复:手动同步 = 从设备恢复备份到云端

总结

"双向自动同步"看起来很美好,但在蓝牙门锁场景下:

  1. 技术上:增量对比、冲突解决都是难题
  2. 成本上:设备资源有限,无法承担复杂同步机制
  3. 必要性上:门锁管理操作频率低,手动同步可接受

简单可靠优于复杂完美。

继续阅读

了解我们最终采用的同步方案,请阅读 数据同步

物联网设备通信协议文档