分布式软总线跨设备任务迁移:可靠状态同步与回滚设计

前言

分布式软总线(Distributed Soft Bus)是鸿蒙"超级终端"能力的底座,让手机、平板、车机之间可以无缝迁移任务、共享状态。但"迁移"默认只是一次性快照——把当前页面/数据推到对端就结束。之后两端各自演进,一旦网络抖动或设备掉线,状态就会分叉。本文给出一个可落地的"版本号 + 操作日志 + 协调者"同步模型,并附带回滚策略。

问题描述

典型痛点:

  • A 设备改了状态,B 设备没收到(网络抖动丢包),两者不一致。
  • A、B 同时改了同一字段,谁覆盖谁?没有协调者就乱。
  • 迁移过程中对端崩溃,A 端已经"认为成功",实际状态残缺。
  • 想撤销上一步操作,发现没存历史快照,无法回滚。

根因:publish/subscribe 是发后不管的,没有 ack、没有版本、没有冲突解决。

细节解析

可靠同步四要素:

  1. 版本号:每条状态带 version,每次变更自增。对端收到低版本直接丢弃,避免旧数据覆盖新数据。
  2. 传操作而非传全量:发"增量操作日志(Op Log)"而不是整坨状态。带宽小、天然可重放、可回滚。
  3. 协调者(主设备):多设备场景必须有唯一主设备裁决冲突(最后写入胜出 / 指定主)。无主则多主互相覆盖。
  4. ack + 重发:发布端维护"已确认"集合,断线重连后补发未确认 Op;对端按 version 去重。

回滚:保留最近 N 个快照,异常时用上一个成功快照 restore(version)

示例代码

定义带版本的状态与操作:

// state.ets
export interface SyncState {
  data: Record<string, Object>;
  version: number;
  devId: string;
}

export interface Op {
  version: number;
  devId: string;
  type: 'set' | 'delete';
  key: string;
  value?: Object;
}

发布端:发操作日志 + 维护确认:

import { distributedSoftBus } from '@kit.DistributedSoftBus';

const confirmed = new Set<number>();

export function sendOp(op: Op) {
  // 通过软总线发布,对端重放该操作
  distributedSoftBus.publish('topic_state_sync', JSON.stringify(op));
  // 简单 ack 机制:订阅回执
  // 未在超时内确认则重发
  scheduleResend(op);
}

function applyOp(state: SyncState, op: Op): SyncState {
  if (op.version <= state.version) return state;   // 丢弃过期操作
  const next = { ...state.data };
  if (op.type === 'set') next[op.key] = op.value!;
  else delete next[op.key];
  return { data: next, version: op.version, devId: op.devId };
}

接收端:按版本重放 + 去重:

distributedSoftBus.subscribe('topic_state_sync', (data: string) => {
  const op: Op = JSON.parse(data);
  if (localState.version >= op.version) return;   // 已应用或过期
  localState = applyOp(localState, op);
  sendAck(op.version);                             // 回执,让发布端移除重发
});

回滚:

const snapshots: SyncState[] = [];   // 最近 N 个
function snapshot() { snapshots.push({ ...localState }); if (snapshots.length > 10) snapshots.shift(); }
function rollback() { localState = snapshots[snapshots.length - 2] ?? localState; }

总结

  • 迁移只是快照,持续同步要自己建机制。
  • 传操作日志 > 传全量;版本号解决覆盖;协调者解决冲突;ack 解决丢包。
  • 回滚靠"保留最近快照",别只存当前态。
  • 验证:A 改→断网→B 改→恢复网络,应能在协调者裁决下合并或回滚到一致点,而非分叉。
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐