我正在为我正在开发的iPad应用程序设置基本同步服务。目标是在iPad应用程序的多个实例中保持数据一致,并在Web上拥有只读版本的数据,从而推出自定义解决方案。
目前的流程如下:
这一切似乎都运转正常。我的问题是如何使用此方法跟踪已删除的对象?我猜我可以为每个实体添加一个'已删除'标志,并在客户端删除某些内容时设置此标志,然后我可以将该更改推送到服务器并使用其余的同步数据。同步完成后,客户端实际上可以删除这些实体。我的问题是:
答案 0 :(得分:6)
如何保留带有UUID和已创建/更新/删除字段的增量历史记录表,可能每个更新都有一个修订号?因此,您保留自上次成功同步以来的一小部分更改清单。
这样,如果删除对象,可以在增量历史记录表中添加一个包含已删除UUID的条目,并将其标记为已删除。与创建和更新的对象相同,您只需要检查增量表,以查看服务器需要删除,更新,创建等的项目。您甚至可以在服务器上存储每个修订版本以支持回滚到以前的版本如果你愿意的话,未来。
我认为修订号比依赖客户的时钟更好,可能会手动更改。
您可以使用NSManagedObjectContext的insertedObjects,updatedObjects,deletedObjects方法在每个保存过程之前创建delta对象:)
我的2美分
答案 1 :(得分:1)
关于您的第二个问题:您可以设计这个,以便服务器不必保留已删除的记录,如果您愿意。让每个应用程序知道给定的数据片段(基于其UUID)是否存储在服务器上(例如,添加existsOnServer属性或类似属性)。这在应用程序中创建新项目时开始为false,但是一旦首次同步到服务器,则设置为true。这样,如果应用程序稍后尝试同步,但未找到UUID,则可以区分这两种情况:如果existsOnServer为false,则此项目是新创建的,应该同步到服务器,但如果为true然后它可以被认为是它之前已经在服务器上,但现在已被删除,所以你也可以在应用程序中删除它。
我可能会反对这种方法,因为它似乎更容易出错(我想象数据库或连接错误被错误地解释为删除)并且在服务器上保留记录通常不是什么大不了的事,但这是可能的。 dzeikei建议的“delta-approach”可以同时使用,因此对服务器上不存在的记录的更新表示它已被删除,而插入则没有。
答案 2 :(得分:1)
是否必须在服务器上保留已删除的对象,完全取决于您的需求。您需要在本地删除一个标记以标记为同步已删除,也可能在服务器上,具体取决于您希望回滚。
我之前已经通过几种方式解决了这个问题。这是一种可能性:
当客户端删除某些内容时,只需将其标记为在本地删除,并在同步期间从服务器中删除(此时您可以从核心数据中清除)。当其他客户端请求访问该数据时,请发回HTTP 404,因为您不再拥有该对象。此时,客户端可以在本地删除该实体。现在,如果客户端请求一个事物列表并且该对象已被删除,那么它将从他返回的事物列表中丢失,这样您就可以检测到并删除它。当我从服务器获得响应并删除任何没有这些ID的本地对象时,我通过创建一个对象ID数组在客户端中执行此操作。
我们在服务器上有一个已删除的字段,但只是为了能够在意外删除某些内容时回滚。
当然,您可以将已删除的对象返回给客户端,以便他们知道要删除但如果您不想在服务器上保留副本,则必须假设客户端将在一个时间范围内全部更新。然后你可以在该时间框架到期后进行垃圾收集。
我真的不喜欢那个解决方案。如果您的数据太重而无法请求所有对象进行完全同步,则可以使用当前的合并策略进行创建和更新,然后运行单独的调用以检查已删除的项目。该调用可以简单地询问客户端应该在设备上具有的所有ID。它可以删除那些不存在的。或者,它可以在客户端上发送所有ID,并返回要删除的ID列表。
如果您想要更加自以为是的建议,我认为您必须提供有关数据性质的更多详细信息。
答案 3 :(得分:1)
如果你没有,你可以看看Cross-Platform Data Synchronization by Dan Grover。这篇关于同步和iOS的论文非常好。
关于您的问题:
您可以避免删除Core Data中的文件并设置“已删除标志”:只需更新文件而不是删除它。您可以创建自己的“删除”方法,实际上会调用并更新记录上的标记。
始终为服务器和每个客户端上的每条记录保留last_sync和last_updated。通过这种方式,您可以随时了解某人是否确实在任何地方进行了更改,并且该更改是否与“真实数据库”同步或更改。
跟踪已删除的文件是一件很难的事情,我想最好的方法是跟踪每个表的同步历史,但这是一项艰巨的任务。最简单的方法是使用这种“真值数据库”类型的配置标记文件,这样就可以保存服务器和客户端上的数据。
答案 4 :(得分:-3)