2013-09-11 3 views
6

Этот вопрос касается того, что я считаю очень распространенной проблемой в разработке Android/iOS, но пока не нашел «стандартного» решения.Синхронизация клиент-сервер через REST

Предположим, что у нас нормальный REST API. База данных сервера содержит (среди прочих) таблицы countries и towns с отношением 1: N.

Клиент (мобильное приложение) хочет сохранить локальный снимок этих двух таблиц. Таким образом, когда он отключен, он может выполнять запросы, которые обычно выполняются над REST, например: «получить список австрийских городов с населением> = 100»?

Как подойти к этому?

Первая проблема: консистенция. Клиент должен иметь моментальный снимок двух таблиц. Если клиент загружает обновления таблицы towns и переходит в автономный режим, некоторые города могут ссылаться на страну, которая не находится в локальной копии таблицы countries.

Вторая проблема: клиент должен загружать только новые/удаленные/измененные строки. Отключите REST и используйте какой-то пользовательский вызов RPC, например get_updates_since(...)?

Третья проблема: как следует синхронизировать локальные изменения в копии базы данных клиента (возможно, в автономном режиме) с сервером? Пользовательские вызовы RPC?

+0

meaby [IT] (http://www.dmytrodanylyk.com/android-data-sync-part-2/?utm_source=Android+Weekly&utm_campaign=55f0ff46e4-Android_Weekly_201&utm_medium=email&utm_term=0_4eb677ad19-55f0ff46e4-337928757) поможет – murt

ответ

5

Я не думаю, что есть серебряная пуля, но шаблон, который вы ищете, - это кеширование. В прошлых проектах я скопировал элементы с сервера на локальное хранилище (SQLite или плоский файл) и поддерживал метаданные о записях для обновления/выгрузки/очистки на основе простых правил. Это не простая проблема, и в итоге получается много кода.

Согласованность: в вашем примере либо убедитесь, что вы загрузили таблицу стран в первую очередь, либо сделайте две операции атомарными - например, сделайте копии «новых» таблиц и замените только свои кешированные версии, если обе копии завершены успешно (удваивается на складе).

Загрузка только новых/удаленных/измененных: да, для этого требуется интеграция клиент/сервер - отметьте все записи (с GMT), запросите метаданные с сервера и пройдите через локальные метаданные, чтобы решить, что делать. (Подсказки UUID на строках полезны).

Синхронизировать локальные изменения: Да, больше интеграции клиент/сервер. См. Выше параграф.

Обработка всех исключений и краевых дел является сложной задачей. Взгляните на problems with iCloud sync'ing CoreData. Возможно, это не справедливое сравнение, поскольку Apple пытается решить эту проблему для полностью распределенной базы данных, но тем не менее интересно читать.

+0

Да, синхронизация, распределенные системы, параллелизм и т. Д. Просто сложно ... – fhucho

4

В настоящее время я работаю над той же задачей - созданием приложения для Android, которое будет синхронизировать информацию с центральной базой данных SQL, используя Azure Mobile Services. Стратегия синхронизации - поддерживать двунаправленную синхронизацию от нескольких клиентов, чтобы обеспечить согласованность данных, тогда как будут заменены только дополнительные изменения.

Позвольте мне предоставить решение ваших проблем. Недавно я написал blog post about sync algorithm для поддержки этих сценариев.

Логика синхронизации будет управляться на стороне клиента из-за связи REST API. Каждая таблица, участвующая в процессе синхронизации, будет иметь соответствующие методы REST Api для операций CRUD.

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

Вторая проблема (скачать только инкрементные изменения) - решение является меткой времени (как упоминал Кевин в своем ответе ниже). Но я бы предложил использовать глобально увеличивающееся значение, поддерживаемое на стороне сервера, чтобы избежать проблем с различиями между метками времени между клиентами и сервером. Для этого неплохо подходит rowversion SQL Server.

Третья проблема (интеграция данных с клиентом) - использование Dirty flag в клиентских таблицах поможет дифференцировать записи, необходимые для загрузки.

Вам также может потребоваться ввести флаг «Удалить» с обеих сторон для обработки удалений между несколькими клиентами.

Смежные вопросы