核心数据云同步 - 需要逻辑帮助

ind*_*gie 14 cloud macos synchronization core-data ios

我正在为我目前正在开发的Core Data应用程序集思广益的云同步解决方案.我计划在完成后为这个代码开源代码,任何人都可以使用他们的核心数据应用程序,所以社区对这个系统应该如何工作的意见非常感谢:-)这就是我在想的:

服务器端


存储提供商

与所有云同步系统一样,存储是这个难题的主要部分.有很多方法可以解决这个问题.我可以设置我自己的服务器进行存储,或者使用像Amazon S3这样的服务,但由于我现在开始使用0美元资金,此时付费存储解决方案不是一个可行的选择.经过一番思考后,我决定选择Dropbox(一个已经很成熟的云同步应用程序和存储提供商).使用Dropbox的优点是:

  • 它是免费的(对于有限的空间)
  • 除了作为存储服务,它还处理云同步
  • 他们最近发布了一个Objective-C SDK,它可以更容易地在Mac和iPhone应用程序中与它进行交互

如果我决定将来切换到不同的存储提供商,我打算在这个云同步框架中添加"服务",基本上允许任何人创建一个服务类来与他们选择的存储提供商进行交互,然后可以简单地插入框架.

存储结构

这是一个非常困难的部分,因此我需要尽可能多的输入.我一直在考虑这样的结构:

CloudSyncFramework
======> [app name]
==========> devices
=============> (device id)
================> deviceinfo
================> changeset
==========> entities
=============> (entity name)
================> (object id)
Run Code Online (Sandbox Code Playgroud)

这个结构的快速解释:

  • 主"CloudSyncFramework"(名称未定)文件夹将包含使用该框架的每个应用程序的单独文件夹
  • 每个app文件夹都包含一个devices文件夹和一个实体文件夹
  • 所述设备的文件夹将包含每个与该帐户注册设备的文件夹.设备文件夹将根据设备ID命名,使用类似[[UIDevice currentDevice] uniqueIdentifier](在iOS上)或序列号(在Mac OS上)获得.
  • 每个设备文件夹包含两个文件:deviceinfochangeset.deviceinfo包含有关设备的信息(例如操作系统版本,上次同步日期,型号等),变更集文件包含自设备上次同步以来已更改的对象的信息.这两个文件都只是简单的NSDictionaries归档到文件中使用NSKeyedArchiver.
  • 每个Core Data实体在entities文件夹下都有一个子文件夹
  • 在每个实体文件夹下,属于该实体的每个对象都将具有单独的文件.该文件将包含带有键值对的JSON字典.

同步同步

这是我几乎完全无能为力的领域之一.我如何处理同时连接和同步云的2台设备?事情似乎很有可能在这里失去同步,甚至数据损坏.

处理迁移

再次,这里另一个无能为力的地区.我如何处理Core Data托管对象模型的迁移?这里最简单的做法似乎就是清理云数据存储并从已经过迁移过程的设备上传数据的新副本,但这似乎有些冒险,并且可能有更好的方法.

客户端


将NSManagedObjects转换为JSON

将属性转换为JSON并不是一项非常艰巨的任务(它有很多代码可以在Web上浮动).关系是这里的关键问题.在这个 stackoverflow帖子中,Marcus Zarra发布了将关系对象本身添加到JSON字典中的代码.但是,他提到这可能会导致无限循环,具体取决于模型的结构,我不确定这是否适用于我的方法,因为我将每个对象存储为单个文件.

我一直在试图找到一种方法来获取ID作为字符串NSManagedObject.然后我可以将JSON中的关系保存为ID数组.我找到的最接近的东西是[[managedObject objectID] URIRepresentation],但这不是一个对象的ID,它更像是持久存储中对象的位置,我不知道它是否具体足以用作对象的引用.

我想我可以为每个对象生成一个UUID字符串并将其保存为属性,但我愿意接受建议.

将更改同步到云

出现在我头脑中的第一个(也是最好的)解决方案是监听NSManagedObjectContextObjectsDidChangeNotification获取已更改对象的列表,然后在云数据存储中更新/删除/插入这些对象.保存更改后,我需要更新每个其他已注册设备的更改集文件以反映新更改的对象.

这里出现的一个问题是,我将如何处理失败或中断的同步?.我的一个想法是首先将更改推送到云上的临时目录,然后一旦确认成功,就将其与云上的主数据合并,以便同步中间的中断不会损坏数据.然后,我会将需要在云中更新的对象的记录保存到plist文件或其他内容中,以便在下次应用程序连接到Internet时进行推送.

检索已更改的对象

这很简单,设备下载其变更集文件,确定需要更新/插入/删除哪些对象,然后相应地采取行动.

这总结了我对该系统将使用的逻辑的思考:-) 非常感谢任何见解,建议,问题的答案等.

UPDATE

经过大量的思考和阅读TechZens的建议后,我对我的概念进行了一些修改.

我想到的最大变化是让每个设备在云中都有一个单独的数据存储.基本上,每次托管对象上下文保存时(感谢TechZen),它都会将更改上传到该设备的数据存储.更新这些更改后,它将创建一个包含更改详细信息的"changeset"文件,并将其保存到正在使用该应用程序的OTHER设备的changeset文件夹中.当其他设备连接到同步时,它们将通过changeset文件夹并将每个变更集应用于本地数据存储,然后也在云中更新它们各自的数据存储.

现在,如果在帐户中注册了新设备,它将从所有设备中找到最新的数据副本,并将其下载以用作其本地存储.这解决了同步同步的问题并减少了数据损坏的可能性,因为没有"中央"数据存储,每个设备仅触及其数据并且仅更新更改而不是每个设备同时访问和修改相同数据.

有一些明显的冲突情况需要处理,主要是与删除对象有关.如果下载变更集指示应用程序删除当前正在编辑的对象等,则需要有办法处理此问题.

Tec*_*Zen 14

您想看看对云同步的这种悲观看法:为什么云同步将无法工作. 它涵盖了许多你正在努力解决的问题.其中许多很大程度上难以处理.

同步信息期是非常非常非常困难的.添加不同的设备,不同的操作系统,不同的数据结构等,往往会致命地复杂化复杂性.自70年代以来,人们一直在研究这个问题的变种,事情确实没有太大改善.

根本问题在于,如果您保持系统的灵活性和可定制性,那么同步所有变体的复杂性将随着定制数量的增加而呈指数级增长.如果你使它变得僵硬,你可以同步,但你可以同步的内容有限.

我如何处理同时连接和同步云的2台设备?

如果你明白这一点,你就会变得富有.对于当前的云同步提供商来说,这是一个大问题.他们真正的问题在于你没有"同步"你的合并.软件很难合并,因为很难建立预定义的规则集来描述所有可能的合并.

最简单的系统是建立规范设备或设备层次结构,以便系统始终知道选择哪个输入.然而,这会破坏灵活性.

我如何处理Core Data托管对象模型的迁移?

Core Data模型的迁移在很大程度上与服务器无关.这是Core Data内部管理自己的东西.模型迁移更新模型,即实体图,而不是实际数据.

将NSManagedObjects转换为JSON

建模关系很难,特别是对于不像Core Data那样容易支持它的工具.但是,永久管理对象ID的URI应该用作UUID,将对象固定到特定设备上特定存储中的特定位置.它在技术上并不保证是普遍独特的,但它足够接近所有实际用途.

将更改同步到云

我认为你把Core Data的实现细节与云本身混淆了.如果您使用NSManagedObjectContextObjectsDidChangeNotification,每次观察到的上下文发生变化时,无论这些更改是否持久,您都会唤起网络流量.根据应用程序的不同,这可能会在几分钟内连接数千次.相反,您只想在最多保存上下文时进行同步.

这里出现的一个问题是,我将如何处理失败或中断的同步?

在同步完成之前,您不会提交更改.这是一个大问题,导致数据损坏.同样,您可以拥有灵活性,复杂性和脆弱性或不灵活性,简单性和稳健性.

检索更改的对象:这很简单,设备下载其变更集文件,确定需要更新/插入/删除的对象,然后相应地采取行动

如果你有一个不灵活的数据结构,这很简单.描述对灵活数据结构的更改是一场噩梦.

不确定我是否有任何帮助.没有一个问题有优雅的解决方案.大多数设计师最终都采用刚性和/或缓慢,强力迭代合并.