在多个实体之间同步数据最聪明和简单的方法是什么?

在当今世界,大量计算机,移动设备或Web服务共享数据或像集线器一样工作,同步变得更加重要。 正如我们都知道同步不是最舒适的解决scheme,最好不要同步。

我仍然很好奇你将如何实现一个同步解决scheme来在多个实体之间进行同步。 已经有很多不同的方法,比如比较一个已更改的date字段或散列,并使用最新的数据,或者让用户在冲突情况下select他想使用的内容。 另一种方法是尝试自动合并冲突的数据(在我看来,这并不是那么聪明,因为机器无法猜测用户的意思)。

无论如何,下面是一些与同步相关的问题,我们应该在开始实施同步之前回答:

  • 什么是最近的数据? 我如何表示呢?
  • 如果发生冲突,我该怎么办? 合并? 我是否提示并询问用户该怎么做?
  • 当我处于不一致的状态(例如,由于移动式networking连接而断开连接)时,我该怎么办?
  • 当我不想陷入不一致的状态时,我该怎么办?
  • 如何恢复当前中断的同步?
  • 如何处理数据存储(例如,Web服务上的MySQL数据库,iPhone上的Core Data;以及如何合并/同步数据,而不需要大量的胶水代码)?
  • 我应该如何处理同步期间发生的用户编辑(在后台运行,因此UI未被阻止)?
  • 我如何以及在哪个方向传播更改(例如,用户在他的计算机上创build“Foo”条目并且不同步;然后他正在移动并创build另一个“Foo”条目;当他尝试同步两个设备时会发生什么)? 用户是否有两个具有不同唯一ID的“Foo”条目? 用户只有一个入口,但哪一个?
  • 我有分层数据时应该如何处理同步? 自顶向下? 自下而上? 我是否以primefaces的方式对待每一个条目,还是只看一个超级节点? 简单的事情和投入太多的时间之间的权衡有多大?

还有很多其他的问题,我希望我能激励你。 同步是一个相当普遍的问题。 一旦find了一个好的,多function的同步方法,应该更容易将其应用于具体应用,而不是从头开始思考。 我意识到,已经有很多应用程序试图解决(或成功解决)同步,但是它们已经相当具体,并且不能给同步方法提供足够的答案。

在我工作的地方,我们开发了一个“离线”版本的主要(networking)应用程序,用户可以在他们没有互联网接入的地方使用笔记本电脑(我不确定这些地方有多less实际存在这些天,但我已经被告知他们这样做))。 当用户回到主站点时,他们需要将他们离线input的数据与我们的主应用程序同步。

所以,要回答你的问题:

  • 什么是最近的数据? 我如何表示呢?

我们在每个表上都有一个LAST_UPDATED_DATE列。 服务器会跟踪同步发生的时间,所以当离线应用程序请求同步时,服务器会说:“嘿,只给我自从这个date以来更改的数据”。

  • 如果发生冲突,我该怎么办? 合并? 我是否提示并询问用户该怎么做?

在我们的情况下,离线应用程序只能够更新所有数据的相对较小的子集。 由于每条logging都是同步的,我们检查它是否是这些情况之一,如果是,那么我们比较LAST_UPDATED_DATElogging在线和离线的logging。 如果date不同,那么我们也检查这些值(因为如果它们都被更新为相同的值,则不会发生冲突)。 如果有冲突,我们logging差异,设置一个标志,说至less有一个冲突,并继续检查其余的细节。 一旦这个过程完成,那么如果设置了“isConflict”标志,用户可以进入一个显示差异的特殊页面,并确定哪个数据是“正确的”版本。 这个版本然后保存在主机上,“isConflict”标志被重置。

  • 当我不想陷入不一致的状态时,我该怎么办?
  • 如何恢复当前中断的同步?

那么,我们尽量避免陷入一个不一致的状态。 如果由于某种原因导致同步中断,则last_synchronisation_date不会更新,因此下一次启动同步时,将从与之前(中断的)同步的开始date相同的date开始。

  • 如何处理数据存储(例如,Web服务上的MySQL数据库,iPhone上的Core Data;以及如何合并/同步数据,而不需要大量的胶水代码)?

我们在两个应用程序上使用标准数据库,在两者之间使用标准数据 这些对象被序列化为XML(并且通过gzip来加速传输)以用于实际的同步过程,然后在每一端解压缩/反序列化。

  • 我应该如何处理同步期间发生的用户编辑(在后台运行,因此UI未被阻止)?

这些编辑将在同步开始date之后进行,因此在下一次同步之前不会在另一侧进行拾取。

  • 我如何以及在哪个方向传播更改(例如,用户在他的计算机上创build“Foo”条目并且不同步;然后他正在移动并创build另一个“Foo”条目;当他尝试同步两个设备时会发生什么)? 用户是否有两个具有不同唯一ID的“Foo”条目? 用户只有一个入口,但哪一个?

这取决于你决定如何处理这个特定的Foo …即取决于Foo的主键是什么以及如何确定一个Foo是否与另一个相同。

  • 我有分层数据时应该如何处理同步? 自顶向下? 自下而上? 我是否以primefaces的方式对待每一个条目,还是只看一个超级节点?

同步是primefaces的,所以如果一个logging失败,那么整个过程被标记为不完整,类似于颠覆提交事务。

  • 简单的事情和投入太多的时间之间的权衡有多大?

我不确定你的意思,但是我想说这一切都取决于你的情况和你想同步的数据types/数量。 devise和实施过程可能需要很长时间,但这是可能的。

希望能帮助你,或者至less给你一些想法! 🙂

可能“不是一个真正的问题”,这里不是一个真正的答案:

我认为分布式版本控制系统(如Mercurial或Git)已经找出了很大的一部分。 但是,他们要求人们接受可以有多个“最新”版本,有时需要手动解决的更新有时会发生冲突。 另外,如果你对保留整个变更历史不感兴趣,这些系统中会有相当多的开销(但是最近的历史当然需要寻找共同的祖先来确定这两个版本之间的关系)。

但是我同意你的观点,在这个世界上,每个人都有数据分布在多个设备和服务上,自动跟踪和分发更新的需求将变得非常紧迫,应用程序使用的通用文件格式将包含足够的元数据促进某种智能合并行为。 但是这种行为可能不得不在应用程序级别上发生,因为没有通用的方法来解决冲突的更新。

与此同时,iTunes-iPod的方法是最简单的:您只有一个主库,每个设备从那里拉。 显然,在所有场景(尤其是涉及多个用户的情况下),单主控同步并不是很令人满意,但是如果有更多的应用程序提供这样的选项,我将不胜感激(pet peeve:我有三个Mac ,三个iPhoto的安装,如果他们自动同步从一个专用主​​,就像照片同步到我的iPod,这将是一个改进)。

感谢GaZ的详细回应。 我有几个后续问题:

如果你使用时间戳,你如何处理不准确的时间设置(小的差异,例如1-5秒)? 他们多久出现一次? 对于处理不同的数据更改,是不是版本控制(像SVN这样做)?

我知道你只能在两个时间戳,last_synchronisation_date(每个客户端)和现在之间获取数据?

当用户没有解决冲突时,你会做什么? 您是不是同步用isConflict标志标记的数据,或者是否添加了另一个冲突,那么当用户决定解决所有冲突时,可以在两个以上版本的实体之间进行select? 或者如果有一些标记为冲突的数据,你是否同步?

虽然它在微软生态系统中确实很有用,但您可以学习移动应用程序块 。