macos - 核心数据云同步 - 需要逻辑方面的帮助

标签 macos core-data synchronization cloud ios

我正在为我目前正在开发的 Core Data 应用程序集思广益地讨论云同步解决方案。我计划在完成后为此开源代码,供任何人与他们的 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)
    

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

  • 同时同步

    这是我几乎完全一无所知的领域之一。 我将如何处理同时连接和同步云的 2 台设备? 这里似乎存在不同步甚至数据损坏的高风险。

    处理迁移

    再一次,这里是另一个毫 headless 绪的区域。 我将如何处理 Core Data 托管对象模型的迁移? 这里最简单的方法似乎只是将云数据存储区擦干净,然后从经过迁移过程的设备上传数据的新副本,但这似乎有点冒险,可能还有更好的方法。

    客户端

    将 NSManagedObjects 转换为 JSON

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

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

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

    将更改同步到云

    为此我想到的第一个(也是最好的)解决方案是听 NSManagedObjectContextObjectsDidChangeNotification获取已更改对象的列表,然后在云数据存储中更新/删除/插入这些对象。保存更改后,我需要更新 变更集每个其他已注册设备的文件以反射(reflect)新更改的对象。

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

    检索更改的对象

    这相当简单,设备下载它的变更集文件,找出哪些对象需要更新/插入/删除,然后采取相应的行动。

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

    更新

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

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

    现在,如果使用该帐户注册了新设备,它将从所有设备中找到数据的最新副本,并将其下载以用作其本地存储。 这就解决了同步同步的问题并且减少了数据损坏的机会,因为没有“中央”数据存储,每个设备只接触它的数据,只是更新更改,而不是每个设备同时访问和修改相同的数据。

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

    最佳答案

    你想看看这个对云同步的悲观看法:Why Cloud Sync Will Never Work.
    它涵盖了您正在努力解决的许多问题。其中许多在很大程度上是难以处理的。

    同步信息周期非常、非常、非常困难。添加不同的设备、不同的操作系统、不同的数据结构等,往往会导致复杂性的增加。自 70 年代以来,人们一直在研究这个问题的变体,但情况确实没有太大改善。

    根本问题是,如果您让系统保持灵活和可定制,那么同步所有变化的复杂性会随着定制数量的增加而呈指数级增长。如果你让它僵化,你可以同步,但你可以同步的内容是有限的。

    How would I handle 2 devices connecting and syncing with the cloud at the same time?



    弄明白了,你就发财了。对于当前的云同步提供商来说,这是一个大问题。他们真正的问题是你没有“同步”你的合并。软件在合并方面很糟糕,因为它很难建立一个预定义的规则集来描述所有可能的合并。

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

    How would I handle migrations of the Core Data managed object model?



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

    Converting NSManagedObjects into JSON



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

    Syncing changes to the cloud



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

    One problem that comes up here is, how would I handle a failed or interrupted sync?



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

    Retrieving changed objects: This is fairly simple, the device downloads its changeset file, figures out which objects need to be updated/inserted/deleted, then acts accordingly



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

    不知道我是否帮助过任何人。这些问题都没有优雅的解决方案。大多数设计人员最终都采用僵化和/或缓慢的蛮力迭代合并。

    关于macos - 核心数据云同步 - 需要逻辑方面的帮助,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3327752/

    相关文章:

    objective-c - Mac OS X 应用程序在其窗口没有焦点时速度变慢

    objective-c - 使用MD5算法时出错

    swift - 如何处理主队列上的多个 moc

    macos - 按 ID 对核心数据排序

    cocoa - 核心数据延迟加载问题

    java - 反向读写锁

    authentication - CouchDB 和 PouchDB 之间的过滤同步

    java - 在命令行上增加 jMeter 的内存

    cocoa - 全屏狮子复合动画

    c++ - 在析构函数中获取锁是一个坏主意吗?