同步常见分布式数据的最佳实践

时间:2009-08-12 12:33:43

标签: database synchronization distributed offline

我有一个支持离线模式的互联网应用程序,用户可能会在用户重新联机时创建将与服务器同步的数据。因此,我在我的数据库中使用UUID用于标识,因此断开连接的客户端可以生成新对象而不必担心使用其他客户端使用的ID等。但是,这对于此用户拥有的对象非常有效是多个用户共享的对象。例如,用户使用的标记可能是全局的,远程数据库无法保存Universe中所有可能的标记。

如果离线用户创建了一个对象并为其添加了一些标记。假设用户的本地数据库中不存在这些标记,因此软件会为它们生成UUID。现在,当这些标签同步时,需要通过解决过程来解决任何重叠。某种方法可以将远程数据库中的任何现有标记与本地版本进行匹配。

一种方法是使用一些进程,通过自然键(在标记的情况下为名称)来解析全局对象,并且本地数据库必须用全局数据库中的对象替换它的现有对象。当与其他对象有许多连接时,这可能会很混乱。有事告诉我要避免这种情况。

另一种处理方法是使用两个ID。一个全局ID和一个本地ID。我希望使用UUID可以帮助避免这种情况,但我会在使用单个UUID和使用两个拆分ID之间来回切换。使用此选项让我想知道我是否让问题失控。

另一种方法是通过非共享对象跟踪所有更改。在此示例中,用户分配标记的对象。当用户同步其脱机更改时,服务器可能会将其本地标记替换为全局标记。下次此客户端与服务器同步时,它会检测到非共享对象的更改。当客户端拉下该对象时,他将收到全局标记。该软件将简单地重新保存非共享对象,将其指向服务器的标签并孤立其本地版本。这方面的一些问题是完全同步的额外往返,以及刚刚孤立的本地数据库中的额外数据。当系统处于同步状态之间时,是否还会出现其他问题或错误? (即尝试与服务器通信并向对象发送本地UUID等)。

另一种选择是避免常见对象。在我的软件中,这可能是一个可接受的答案。我没有在用户之间进行大量的对象共享,但这并不意味着我将来不会这样做。这意味着如果我需要添加这些类型的功能,选择此选项可能会在将来使我的软件瘫痪。这个选择有后果,我不确定我是否已经完全探索过它们。

所以我正在寻找任何类型的最佳实践,处理此类系统的现有算法,选择指南等。

3 个答案:

答案 0 :(得分:5)

根据您要为用户提供的应用程序语义,您可以选择不同的解决方案。例如,如果您实际上是在谈论使用关键字标记离线用户创建的对象,并希望在不同用户创建的多个对象之间共享标记,那么使用“text”标记就可以了,如您所建议的那样。一旦合并了每个人的更改,将共享具有相同“文本”的标签,例如“这是令人敬畏的”。

还有其他方法可以处理对共享对象的断开连接更新。 SVN,CVS等版本控制系统尝试自动解决冲突,何时不能,只会告诉用户存在冲突。您也可以这样做,只需告诉用户有并发更新,用户必须处理解决方案。

或者,您也可以将更新记录为更改单位,并尝试将更改组合在一起。例如,如果您的共享对象是画布,并且您的应用程序语义允许在同一画布上共享绘图,那么从A点到B点绘制一条线的断开连接的更新,以及从C点到点绘制一条线的另一个断开连接的更新D,可以组成。在这种情况下,如果将这两个更新保留为两个操作,则可以订购这两个更新,并且在重新连接时,每个用户都会上载其所有断开连接的操作,并应用其他用户的缺失操作。您可能需要某种排序规则,可能基于版本号。

另一种选择:如果无法自动协调对共享对象的更新,并且您的应用程序语义不支持通知用户并要求用户解决由于断开连接更新而导致的冲突,那么您还可以使用版本树来处理此问题。对共享对象的每次更新都会创建一个新版本,并将过去的版本作为父版本。当来自两个不同用户的共享对象的断开连接更新时,两个单独的子版本/叶节点来自相同的父版本。如果应用程序的内部状态表示形式是此版本树,则应用程序的内部状态尽管断开连接更新仍然保持一致,并且您可以通过其他方式处理版本树的两个分支(例如,让用户知道分支并为其创建工具)合并分支,如源控制系统)。

只是几个选项。希望这会有所帮助。

答案 1 :(得分:3)

完全出于左外野的建议,我想知道使用像CouchDB这样的东西是否适用于你的情况。它的replication features可以为您处理很多在线/离线同步问题,包括允许应用程序在出现冲突时解决冲突的机制。

答案 2 :(得分:2)

您的问题与SVN等版本系统非常相似。你可以从那些人那里得到榜样。

每个用户都有一组个人对象以及他们需要的任何共享对象。在本地,他们将像拥有所有对象一样工作。

在同步期间,客户端将首先下载对象中的任何更改,并自动同步显而易见的内容。在您的示例中,如果来自服务器的新标记具有相同的名称,则它将在本地系统上相应地更新UUID。

这也是一个很好的地方,可以检测和处理从另一个客户端提交的数据,但由同一个用户提交。

一旦客户端拥有更新和合并的数据版本,您就可以进行上传。

将会进行往返,但我认为没有办法做到这一点,不会使数据结构过于复杂,并且在进行同步时会有潜在的陷阱。