冲突解决方案
当两个或多个用户独立对同一数据进行更改时,就会发生冲突。 这可能是由于设备和服务器之间的延迟或连接中断造成的。 在这种事件, Atlas Device Sync会自动使用冲突解决策略来合并更改。 具体来说, Device Sync使用操作转换来处理冲突解决,操作转换是一设立保证最终一致性的规则,这意味着所有客户端的版本最终将收敛到相同的状态。 即使按不同顺序进行更改也是如此。
必须了解规则才能确保结果一致,但好处是,通过遵循这些规则,可以让设备完全离线工作,并且在融合时仍能得出有意义的结果。
本页使用遛狗应用示例来说明Device Sync如何解决冲突。 在此应用中,Matt 和 Sarah 都是遛狗者,他们使用该应用来追踪客户的狗及其遛狗时间表。
冲突解决规则
从宏观层面来看,规则如下:
- 始终删除 (delete always wins)。
- 如果一侧删除了一个对象,即使另一侧稍后对其进行了更改,该对象也将始终保持删除状态。
- 始终最后更新 (last update wins)。
- 如果两侧更新相同的属性,Device Sync 将保留最近更新的值。
- 列表中的插入项按时间排序。
- 如果两个项目被插入到同一位置,则先插入的项目将排在另一个项目之前。这意味着,如果双方都将项目附加到列表末尾,则将按插入时间的顺序包含这两个项目。
- 主键指定对象标识。
- 如果双方都创建具有相同主键的同类对象,则它们将被视为同一对象的实例。
例子
解决两个用户之间的冲突
Matt 和 Sarah 正在处理他们的遛狗业务数据。Matt 删除了客户的一只狗 Doug 的数据,因为他们不用再遛这只狗了。当 Sarah 外出没有互联网连接时,她会在本地离线版本上编辑 Doug 所需的步行时间数据,因为她不知道 Matt 特删除了 Doug 的数据。
Sarah 恢复互联网连接后,她所做的更改将被发送到服务器。服务器将向她发送 Matt 的删除操作。根据 Device Sync 的冲突解决规则,删除操作始终获胜,因此,将保留 Matt 的删除操作而不是 Sarah 所做的编辑。服务器不会将 Sarah 所做的编辑发送到 Matt 的设备。Matt 和 Sarah 的设备上的数据再次一致。
特殊注意事项
计数器
使用整数进行计数是一种特殊情况。大多数编程语言实施递增操作(如 v
+= 1
)的方式是读取值、递增结果,然后重新存储回原位置。如果有多方同时执行递增(它们可能都读取 10,将其递增到 11,当合并时,将得到结果 11,而不是预期的 12),这显然不起作用。
为了支持这种常见情况,我们提供了一种方法来表达是否递增(或递减)值,并提供足够的提示,以便合并可以达到正确的结果。可以选择更新整个值,也可以按照传达更多含义的方式对其进行编辑,从而能够更精确地控制冲突解决。
嵌套集合
嵌套集合的处理方式与嵌入式对象类似。 也就是说,它们被视为具有特定父对象的子对象。 对父对象的任何更新始终会在冲突解决中获胜,即使它会覆盖子对象。
对嵌套集合的更新解析如下:
如果多个设备更新同一个现有嵌套集合,Device Sync 会使用普通冲突解决规则来合并这两个更改。
如果多个设备创建嵌套在同一父对象中的新唯一集合,则适用“最后更新获胜”规则,并且 Device Sync 会使用最后更新进行的更新覆盖所有其他更新。
例如,Sarah 和 Matt 的遛狗应用程序中的客户详细信息被建模为嵌套在父client
属性中的数组。 Sarah(以及后来的 Matt)均会离线时在各自的设备上为同一客户创建一个新的详细信息集合。 当设备同步时,Device Sync 会保留 Matt 创建的条目,因为他的更新(创建新的嵌套详细信息集合)是最后一次进行的。
随后,Sarah 和 Matt 分别对新创建的详细信息条目进行了独特的更新。 Device Sync 将根据正常的冲突解决规则合并这些更新,按时间顺序将新项目或修改项目插入到列表中。
字符串
Device Sync 将字符串的值解释为一个整体,并且不会基于每个字符合并冲突。例如,这意味着,如果在字符串中插入或删除字符或子字符串,Device Sync 会将其视为字符串整个值的替换项。
字典
Device Sync将删除字典键视为更新,而不是删除。 因此,将应用“最后更新获胜”规则,而不是“删除始终获胜”规则。
示例,遛狗应用包含每只狗的可选详细信息集合,这些信息作为键值输入。 当两个用户都离线时,Sarah 删除了一只狗的整个favorite toy
条目,后来 Matt 将同一只狗的最喜欢的玩具更新为tennis ball
。 当两者都重新在线时, Device Sync会将两者视为对favorite toy
条目的更新,并应用 Matt 的更新,因为他是在 Sarah 删除条目后进行的更新。
自定义冲突解决
一般来说,Device Sync 的冲突解决应该适用于大多数用途,无需进行自定义。也就是说,自定义冲突解决的典型方法是将属性类型从字符串更改为列表。然后,每一方都可以将其更新添加到列表中,并直接在数据模型中应用想要的任何冲突解决规则。可以使用此方法来实施最大值、最小值、最先写入获胜、最后写入获胜或能想到的任何其他类型的解决方案。
总结
Device Sync 实施冲突解决系统,允许多个离线写入者同时写入,并且最终仍会融合得出相同的结果。
- 冲突解决系统遵循四个规则:
始终删除 (delete always wins)。
最后更新获胜。
列表中的插入项按时间排序。
主键指定对象标识。
计数器、嵌套集合和字符串是客户端代码中需要注意的特殊情况。