脱机数据同步

脱机数据同步是 Azure 移动应用的一项 SDK 功能。 数据存储在本地存储中。 当应用处于脱机状态时,你仍可创建、修改和搜索数据。 当设备处于联机状态时,数据会与 Azure 移动应用服务同步。 当客户端和服务上更改同一记录时,SDK 支持冲突解决。

脱机同步具有几个优势:

  • 提高应用响应能力
  • 在网络连接不佳时提高应用可靠性
  • 限制高延迟或按流量计费的网络使用
  • 支持断开连接的使用

以下教程演示如何使用 Azure 移动应用将脱机同步添加到移动客户端:

什么是同步表?

Azure 移动应用 SDK 提供 IRemoteTable<T>,用于直接访问服务。 如果设备没有网络连接,操作将失败。 同步表(由)IOfflineTable<T>针对本地存储提供相同的操作。 稍后,本地存储可以与服务同步。 在执行任何操作之前,必须初始化本地存储。

什么是本地存储?

本地存储是客户端设备上的数据持久层。 大多数平台将 SQLite 用于本地存储,但 iOS 使用 Core Data。 你也可以实现自己的本地存储。 例如,使用带有 SQLCipher 的 SQLite 版本来生成加密的存储。

脱机同步的工作原理是什么?

客户端代码控制本地更改何时与数据同步服务。 推送本地更改之前 ,不会向服务发送 任何内容。 同样,仅当拉取数据时,本地存储才会填充新的或更新的数据。

可以推送所有表、表列表或一个表的挂起操作:

// All tables
await client.PushTablesAsync();

// A list of tables
var tablesToPush = new string[] { "table1", "table2" };
await client.PushTablesAsync(tablesToPush);

// A single table
await table.PushItemsAsync();

同步

推送操作将操作队列中的所有待处理更改发送到服务。 挂起的更改通过 HTTP REST 调用发送到服务,后者反过来会修改数据库。

推送操作完成后,才能进行拉取操作。 拉取操作将从服务中拉取已更改的数据并将其存储在本地存储中。

隐式推送

如果针对具有挂起的本地更新的表执行拉取,则拉取将首先执行该表的推送。 此推送有助于最大程度减少已排队的更改与服务器中新数据之间的冲突。 可以选择性地通过在以下项中PullOptions设置PushOtherTables来配置所有表的推送:

var pullOptions = new PullOptions { PushOtherTables = true };
await table.PullItemsAsync(pullOptions);

拉取记录子集

可以选择指定用于确定哪些记录应包含在脱机数据库中的查询。 例如:

var query = table.CreateQuery().Where(x => x.Color == "Blue");
await table.PullItemsAsync(query);

增量同步

Azure 移动应用实现增量同步。仅提取自上次拉取操作以来已更改的记录。 增量同步可节省处理大型表的时间和带宽。

对于每个唯一查询, UpdatedAt 最后一个成功传输的记录的字段作为令牌存储在脱机存储中。 最后一 UpdatedAt 个值存储在增量令牌存储中。 增量令牌存储作为脱机存储中的表实现。

性能和一致性

同步有时会过早停止。 例如:

  • 用于同步的网络在同步过程中变得不可用。
  • 在同步期间强制关闭应用程序。

为了最大程度地降低脱机数据库中一致性问题的风险,每个记录都会在收到时写入数据库。 可以选择性地决定分批将记录写入数据库。 批处理操作可提高拉取操作期间脱机数据库写入的性能。 但是,它们还会增加表元数据与表内数据不一致的风险。

可以按如下所示优化写入之间的间隔:

var pullOptions = new PullOptions { WriteDeltaTokenInterval = 25 };
await table.PullItemsAsync(pullOptions);

此代码收集成批 25 条记录的写入。 性能测试表明,性能最多可提高 25。 WriteDeltaTokenInterval大于 25 的值不会显著改善性能。

清除

可以使用 ..清除本地存储 IOfflineTable<T>.PurgeItemsAsync的内容。 如果客户端数据库中存在过时数据,或者想要取消卡所有挂起的更改,则可能需要清除。 清除操作会从本地存储中清除表。 清除表:

await table.PurgeItemsAsync("", new PurgeOptions());

如果表中存在挂起的更改,该方法 PurgeItemsAsync()InvalidOperationException 引发错误。 在这种情况下,可以强制清除:

await table.PurgeItemsAsync("", new PurgeOptions { DiscardPendingOperations = true });

清除是清理脱机存储中的表的最后手段,因为它会擦除缓存中的所有记录,并要求重新下载这些记录。