Синхронизация облачных данных Core Data - нужна помощь с логикой

Я нахожусь в центре мозгового штурма решения для облачной синхронизации для приложения Core Data, которое я сейчас разрабатываю. Я планирую открыть исходный код для этого, как только это будет сделано, для тех, кто использует их приложения с основными данными, поэтому вклад сообщества в то, как эта система должна работать, очень ценится:-) Вот что я думаю:

Сторона сервера


Поставщик средств хранения

Как и во всех облачных системах синхронизации, хранилище является основной частью головоломки. Есть много способов справиться с этим. Я могу настроить свой собственный сервер для хранения или использовать службу, такую ​​как Amazon S3, но поскольку я начинаю с капитала в 0 долларов, на данный момент платное решение для хранения данных не является жизнеспособным вариантом. После некоторого раздумья я решил согласиться с Dropbox (уже зарекомендовавший себя приложение для облачной синхронизации и хранилище). Преимущества использования Dropbox:

  • Это бесплатно (для ограниченного пространства)
  • Помимо службы хранения данных, она также обрабатывает синхронизацию с облаками
  • Недавно они выпустили SDK Objective-C, который упрощает взаимодействие с ним в приложениях Mac и iPhone.

В случае, если я решит переключиться на другого поставщика хранилища в будущем, я намерен добавить "сервисы" в эту инфраструктуру облачной синхронизации, в основном позволяя любому создавать класс обслуживания для взаимодействия с их выбором поставщика хранилища, который может затем просто подключаться к инфраструктуре.

Структура хранилища

Это очень сложная часть, чтобы понять, так что мне нужно столько, сколько я могу здесь. Я думал о такой структуре:

CloudSyncFramework
======> [app name]
==========> devices
=============> (device id)
================> deviceinfo
================> changeset
==========> entities
=============> (entity name)
================> (object id)

Краткое объяснение этой структуры:

  • Основная папка "CloudSyncFramework" (имя не определено) будет содержать отдельные папки для каждого приложения, использующего фреймворк
  • Каждая папка приложения содержит папку устройств и папку сущности
  • В папке устройства будет указана папка для каждого устройства, зарегистрированного в учетной записи. Папка устройства будет называться в соответствии с идентификатором устройства, полученным с использованием чего-то вроде [[UIDevice currentDevice] uniqueIdentifier] (на iOS) или серийного номера (в Mac OS).
  • Каждая папка устройства содержит два файла: deviceinfo и changeet. deviceinfo содержит информацию об устройстве (например, версия ОС, последняя дата синхронизации, модель и т.д.), а файл changeet содержит информацию об объектах, которые были изменены с момента последнего синхронизированного устройства, Оба файла будут просто простыми NSDictionaries, заархивированными в файлы с помощью NSKeyedArchiver.
  • Каждый объект Data Data имеет подпапку в папке сущности
  • Под каждой папкой сущности каждый объект, принадлежащий этому объекту, будет иметь отдельный файл. Этот файл будет содержать словарь JSON с парами ключ-значение.

Синхронная синхронизация

Это одна из тех областей, где я почти совершенно не знаю. Как я могу обрабатывать 2 устройства, которые одновременно соединяются и синхронизируются с облаком?. Кажется, существует высокий риск того, что здесь не получается синхронизация или даже повреждение данных.

Обработка миграции

Еще раз, другая невежественная область здесь. Как я могу обрабатывать миграции модели объектов, управляемых базовыми данными?. Проще всего сделать здесь, похоже, просто очистить хранилище данных облачных данных и загрузить новую копию данных с устройства, которое прошли процесс миграции, но это кажется несколько рискованным, и может быть лучший способ.

Клиентская сторона


Преобразование NSManagedObjects в JSON

Преобразование атрибутов в JSON - это не очень сложная задача (это много кода для нее, плавающего по сети). Здесь важны отношения. В этом postoverflow post, Marcus Zarra отправляет код, в который сами объекты отношений добавляются в словарь JSON. Однако он упоминает, что это может вызвать бесконечный цикл в зависимости от структуры модели, и я не уверен, что это будет работать с моим методом, потому что я храню каждый объект как отдельный файл.

Я пытаюсь найти способ получить идентификатор в виде строки для NSManagedObject. Тогда я мог бы сохранить отношения в JSON как массив идентификаторов. Самое близкое, что я обнаружил, это [[managedObject objectID] URIRepresentation], но это не действительно идентификатор для объекта, его больше места для объекта в постоянном хранилище, и я не знаю, достаточно ли его достаточно для использования в качестве ссылки для объекта.

Я предполагаю, что я могу создать строку UUID для каждого объекта и сохранить ее как атрибут, но я открыт для предложений.

Синхронизация изменений в облаке

Первое (и еще лучшее) решение, появившееся в моей голове, состояло в том, чтобы прослушать NSManagedObjectContextObjectsDidChangeNotification, чтобы получить список измененных объектов, а затем обновить/удалить/вставить эти объекты в хранилище облачных данных. После того, как изменения сохранены, мне нужно будет обновить файл changeet для каждого другого зарегистрированного устройства, чтобы отразить вновь измененные объекты.

Одна из проблем, которая возникает здесь, - , как я могу обрабатывать неудачную или прерванную синхронизацию?. Одна из моих идей заключается в том, чтобы сначала вносить изменения во временный каталог в облаке, а затем, как только это было подтверждено как успешное, объединить его с основными данными в облаке, чтобы прерывание в середине синхронизации не испортилось данные. Затем я бы сохранил записи объектов, которые необходимо обновить в облаке, в файл plist или что-то еще, чтобы быть нажатым в следующий раз, когда приложение подключено к Интернету.

Извлечение измененных объектов

Это довольно просто, устройство загружает файл changeet, определяет, какие объекты нужно обновлять/вставлять/удалять, а затем действует соответственно.

И это подводит итог моим мыслям о логике, которую эта система будет использовать:-) Большое понимание, предложения, ответы на проблемы и т.д. приветствуется.

UPDATE

После долгих размышлений и чтения предложений TechZens я придумал некоторые изменения в моей концепции.

Самое большое изменение, которое я придумал, - заставить каждое устройство иметь отдельное хранилище данных в облаке. В принципе, каждый раз, когда контекст управляемого объекта сохраняет (спасибо TechZen), он будет загружать изменения в это хранилище данных устройства. После того, как эти изменения будут обновлены, он создаст файл изменений с изменениями и сохранит его в папках наборов изменений других устройств, которые используют приложение. Когда другие устройства подключаются к синхронизации, они будут проходить через папку набора изменений и применять каждый набор изменений в локальном хранилище данных, а затем обновлять соответствующие хранилища данных в облаке.

Теперь, если новое устройство зарегистрировано в учетной записи, оно найдет самую последнюю копию данных из всех устройств и загрузит ее для использования в качестве своего локального хранилища. Это решает проблему синхронной синхронизации и снижает вероятность повреждения данных, поскольку нет "центрального" хранилища данных, каждое устройство касается только своих данных и просто обновляет изменения, а не все устройства, которые обращаются к ним и изменяют их данные в то же время.

Есть некоторые очевидные конфликтные ситуации, с которыми приходится иметь дело, главным образом, в отношении удаления объектов. Если набор изменений загружается, инструктируя приложение удалить объект, который в настоящее время редактируется, и т.д., Должны быть способы борьбы с этим.

Ответы

Ответ 1

Вы хотите посмотреть на эту пессимистическую реакцию на облачную синхронизацию: Почему Cloud Sync никогда не будет работать. Он охватывает множество проблем, с которыми вы боретесь. Многие из них в значительной степени трудноразрешимы.

Очень, очень и очень сложно синхронизировать период информации. Добавление в разные устройства, различные операционные системы, различные структуры данных и т.д. Часто ускоряют сложность. Люди работают над вариантами этой проблемы с 70-х годов, и вещи действительно не улучшились.

Основная проблема заключается в том, что если вы оставите систему гибкой и настраиваемой, то сложность синхронизации всех вариантов будет экспоненциально экспонироваться в зависимости от количества настроек. Если вы сделаете это жестким, вы можете синхронизировать, но вы ограничены тем, что вы можете синхронизировать.

Как я могу обрабатывать 2 устройства подключение и синхронизация с облаком в то же время?

Если вы это выясните, вы будете богаты. Это большая проблема для текущих поставщиков облачных вычислений. Реальная проблема здесь в том, что вы не "синхронизируете" свое слияние. Программное обеспечение засасывает при слиянии, потому что очень сложно установить предопределенное правило, чтобы описать все возможные слияния.

Простейшей системой является установка либо канонического устройства, либо иерархии устройства, так что система всегда знает, какой вход выбрать. Это, однако, разрушает гибкость.

Как я могу обработать миграцию Объектная модель с управляемой базой данных?

Перенос модели Core Data в значительной степени не имеет отношения к серверу. Это то, что Core Data управляет внутренне для себя. Модель миграции обновляет модель, то есть граф объекта, а не фактические данные.

Преобразование NSManagedObjects в JSON

Моделирование отношений сложно, особенно с инструментами, которые не поддерживают его так же легко, как Core Data. Однако URI идентификатора управляемого управляемого объекта должен служить UUID, который прибивает объект до определенного места в определенном хранилище на определенном устройстве. Это технически не гарантирует универсальность, но достаточно близко для всех практических целей.

Синхронизация изменений в облаке

Я думаю, вы путаете детали реализации Core Data с самим облаком. Если вы используете NSManagedObjectContextObjectsDidChangeNotification, вы будете вызывать сетевой трафик каждый раз, когда наблюдаемый контекст изменяется независимо от того, сохраняются ли эти изменения или нет. В зависимости от приложения, это может привести к подключению тысячи раз в несколько минут. Вместо этого вы хотите синхронизировать только при сохранении контекста.

Одна из проблем, возникающих здесь, заключается в том, как я бы справился с неудачной или прерванной синхронизации?

Вы не вносите изменений до завершения синхронизации. Это большая проблема и приводит к повреждению данных. Опять же, вы можете иметь гибкость, сложность, хрупкость или гибкость, простоту и надежность.

Извлечение измененных объектов: это довольно просто, загрузка устройства его файл набора изменений, показывает, какие объекты должны быть обновлен/вставлен/удален, затем действует соответственно,

Это просто, если у вас есть негибкая структура данных. Описание изменений в гибкой структуре данных - это кошмар.

Не уверен, помог ли я кому-нибудь. Ни одна из проблем не имеет изящных решений. Большинство дизайнеров в конечном итоге с жесткостью и/или медленным, грубой силы итеративного слияния.

Ответ 2

Взгляните на RestKit.

Это проект с открытым исходным кодом, целью которого является помощь в интеграции приложений iOS с облачными данными, включая, но не ограничиваясь, сценарий, в котором для данных на клиенте имеется модель данных ядра.

Недавно я начал использовать его в одном из моих проектов и нашел, что он очень полезен. В сценарии основных данных вы реализуете декларативные сопоставления между вашей моделью данных и контентом, с которого вы получаете, и POST на сервер, и он заботится о таких вещах, как ввод объектов из облака в вашу модель клиента, размещение на сервере новых объектов и включение идентификаторов объектов, сгенерированных сервером, в вашу клиентскую модель, делая все это в фоновом потоке и заботясь обо всех проблемах с потоком данных ядра и т.д.

RestKit отнюдь не является зрелым продуктом, но имеет неплохую основу и немало вещей, которые могут использовать помощь других участников. Особенно, если ваша цель - создать решение с открытым исходным кодом, было бы здорово внести свой вклад и улучшить что-то подобное, вместо того чтобы повторно изобретать новое решение. Если, конечно, вы не видите серьезных различий между тем, что вы имеете в виду, и другими существующими решениями: -)

Ответ 3

Поскольку этот пост был актуальным, доступно несколько новых опций. Возможно разработать решение, и с этими решениями будут поставляться приложения.

Ниже приведен краткий список основных параметров синхронизации Core Data:

  • Встроенная в Apple Core Data/iCloud синхронизация. (Было скалистое начало. Кажется, теперь лучше.)
  • TICDS
  • Wasabi Sync, платная услуга.
  • Simperium (Кажется, отказался.)
  • ParcelKit с Dropbox Datastore API
  • Ensembles, самое последнее. (Раскрытие информации: Я являюсь основателем проекта).

Ответ 4

Мне понравилось, что Apple ответила на мой вопрос для меня с анонсом iCloud SDK, который поставляется с интеграцией Core Data. Win!