Синхронизация ядра данных - нужна помощь с логикой - PullRequest
14 голосов
/ 25 июля 2010

Я нахожусь в процессе мозгового штурма решения облачной синхронизации для приложения 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» (имя не определено) будет содержать отдельные папки для каждого приложения, использующего инфраструктуру
  • Каждая папка приложения содержит папку устройств и сущностей папка
  • Папка devices будет содержать папку для каждого устройства, зарегистрированного в учетной записи. Папка устройства будет названа в соответствии с идентификатором устройства, полученным с использованием чего-то вроде [[UIDevice currentDevice] uniqueIdentifier] (в iOS) или серийного номера (в Mac OS).
  • Каждая папка устройства содержит два файла: deviceinfo и changeset . deviceinfo содержит информацию об устройстве (например, версию ОС, дату последней синхронизации, модель и т. Д.), А файл changeset содержит информацию об объектах, которые изменились с момента последней синхронизации устройства. Оба файла будут просто простыми NSDictionaries, заархивированными в файлы с использованием NSKeyedArchiver.
  • У каждого объекта Core Data есть подпапка в папке entity
  • В каждой папке сущностей каждый объект, принадлежащий этой сущности, будет иметь отдельный файл. Этот файл будет содержать словарь JSON с парами ключ-значение.

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

ОБНОВЛЕНИЕ

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

Самое большое изменение, которое я придумал, состоит в том, чтобы каждое устройство имело отдельный хранилище данных в облаке.По сути, каждый раз, когда контекст управляемого объекта сохраняет (спасибо TechZen), он загружает изменения в хранилище данных этого устройства.После того, как эти изменения будут обновлены, он создаст файл «changeset» с деталями изменений и сохранит его в папках наборов изменений ДРУГИХ устройств, которые используют приложение.Когда другие устройства подключаются к синхронизации, они проходят через папку наборов изменений и применяют каждый набор изменений к локальному хранилищу данных, а затем обновляют свои соответствующие хранилища данных в облаке.

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

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

Ответы [ 4 ]

14 голосов
/ 25 июля 2010

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

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

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

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

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

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

Как бы я справился с миграциями модели управляемых объектов Core Data?

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

Преобразование объектов NSManagedObject в JSON

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

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

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

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

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

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

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

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

1 голос
/ 19 февраля 2014

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

Вот краткий список основных опций синхронизации Core Data:

  1. Базовые основные данные Apple /Синхронизация iCloud.(У него было тяжелое начало. Кажется, сейчас лучше.)
  2. TICDS
  3. Wasabi Sync , платная услуга.
  4. Simperium (кажется заброшенным.)
  5. ParcelKit с Dropbox хранилище данных API
  6. ансамбли , большинствонедавно.(Раскрытие: я основатель проекта)
1 голос
/ 02 сентября 2011

Серьезно посмотрите на RestKit .

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

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

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

0 голосов
/ 29 декабря 2011

Как будто Apple ответила на мой вопрос, объявив о iCloud SDK , которые поставляются в комплекте с интеграцией Core Data. Победа!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...