64

Я ищу некоторые общие стратегии для синхронизации данных на центральном сервере с клиентскими приложениями, которые не всегда находятся в сети.Синхронизация баз данных клиент-сервер

В моем конкретном случае у меня есть приложение для Android-андроида с базами данных sqlite и веб-приложение PHP с базой данных MySQL.

Пользователи смогут добавлять и редактировать информацию о приложении телефона и веб-приложении. Мне нужно убедиться, что изменения в одном месте отражаются повсюду, даже когда телефон не может немедленно связаться с сервером.

Меня не интересует, как передавать данные с телефона на сервер или наоборот. Я упоминаю о своих конкретных технологиях только потому, что не могу использовать, например, функции репликации, доступные для MySQL.

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

ответ

71

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

I.e .: Предположим, что запись № 125 была изменена на сервере 5 января в 10 часов вечера, и одна и та же запись была изменена на одном из телефонов (назовем ее клиентом А) 5 января в 11 вечера. Последняя синхронизация была 3 января. Затем пользователь снова подключается, например, 8 января.

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

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

Это решение чрезвычайно важно, и вы должны весить «роль» клиентов. Особенно, если есть потенциальный конфликт не только между клиентом и сервером, но в случае, если разные клиенты могут изменить одну и ту же запись (записи).

[Предполагая, что # 125 может быть изменен вторым клиентом (Клиент B), существует вероятность того, что Клиент B, который еще не синхронизировался, предоставит еще одну версию той же записи, что делает предыдущее разрешение конфликта moot]

Относительно "", созданного или обновленного "пункт выше ... как вы можете правильно идентифицировать запись, если она была создана на одном из клиентов (при условии, что это имеет смысл в вашей проблемной области)? Предположим, что ваше приложение управляет списком деловых контактов. Если Клиент А говорит, что вы должны добавить недавно созданного Джона Смита, а на сервере есть Джон Смит, созданный вчера клиентом D ... вы создаете две записи, потому что не можете быть уверены, что они не разные люди? Вы попросите пользователя смириться с этим конфликтом?

У клиентов есть «собственность» подмножества данных? То есть если Клиент B настроен как «авторитет» на данные для Области №5, может ли Клиент А изменить/создать записи для Области № 5 или нет? (Это упростит разрешение конфликтов, но может оказаться неосуществимым для вашей ситуации).

Резюмируя основные проблемы:

  • Как определить «идентичность», учитывая, что отдельные клиенты не могли получить доступ к серверу, прежде чем создавать новую запись.
  • В предыдущей ситуации, независимо от того, насколько сложным было решение, может возникнуть дублирование данных, поэтому вы должны предвидеть, как периодически их решать и как информировать клиентов о том, что то, что они считают «Запись № 675», фактически было объединено с/вытеснены Запись № 543
  • Решите, если конфликты будут разрешаться приказном (например, «версия сервера всегда козырей клиента, если первый был обновлен с момента последней синхронизации») или ручного вмешательства
  • в случае от fiat, особенно если вы решили, что клиент имеет приоритет, вы также должны заботиться о том, как обращаться с другими, еще не синхронизированными клиентами, которые могут иметь некоторый re меняется.
  • Предыдущие элементы не учитывают детализацию ваших данных (чтобы упростить описание). Достаточно сказать, что вместо рассуждения на уровне «Запись», как в моем примере, вы можете найти более подходящим для записи изменений на уровне поля. Или работать над набором записей (например, Запись человека + Запись адреса + Запись контактов) одновременно, рассматривая их совокупность как своего рода «Мета-запись».

Библиография:

  • Более подробно об этом, конечно же, на Wikipedia.

  • A simple synchronization algorithm автором Vdirsyncer

  • OBJC article on data synch

  • SyncML®: Synchronizing and Managing Your Mobile Data (книги на O'Reilly Safari)

  • Conflict-free Replicated Data Types

  • Optimistic Replication Ясуши Саито (HP Laboratories) и MARC SHAPIRO (Microsoft Research Ltd.) - ACM Computing Surveys, Vol. V, No. N, 3 2005.

  • Alexander Traud, Juergen Nagler-Ihlein, Frank Kargl и Michael Weber. Синхронизация циклических данных за счет повторного использования SyncML. В материалах девятой Международной конференции по управлению мобильными данными (MDM '08). IEEE Computer Society, Вашингтон, США, 165-172. DOI = 10.1109/MDM.2008.10 http://dx.doi.org/10.1109/MDM.2008.10

  • Lam, F., Lam, N., Wong, R. 2002. Эффективная синхронизация для мобильных данных XML. В материалах Одиннадцатой международной конференции по управлению информацией и знаниями (McLean, Вирджиния, США, 04 - 09 ноября 2002 г.). CIKM '02. ACM, Нью-Йорк, Нью-Йорк, 153-160. DOI = http://doi.acm.org/10.1145/584792.584820

  • Cunha, P. R. and Maibaum, T. S. 1981. Ресурс &equil; абстрактный тип данных + синхронизация - методология для ориентированного на сообщения программирования -. В материалах 5-й международной конференции по разработке программного обеспечения (Сан-Диего, Калифорния, США, 09 - 12 марта 1981 г.). Международная конференция по разработке программного обеспечения.IEEE Press, Piscataway, NJ, 263-272.

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

С Dr.Dobbs сайта:

  • Создание приложения с CE SQL Server и SQL RDA Билл Вагнер 19 мая 2004 (Лучшая практика для разработки приложения как для настольных и мобильных ПК - Windows/.NET)

От arXiv.org:

  • A Conflict-Free Replicated JSON Datatype - документ описывает реализацию JSON CRDT (бесконфликтного Repli cid datatypes - CRDTs - это семейство структур данных, которые поддерживают одновременную модификацию и гарантируют конвергенцию таких параллельных обновлений).
+0

Благодарим вас за ответ. Мне очень интересно читать о часто используемых/возможных решениях (плюсах, минусах, сравнениях) для проблем, которые вы наметили. –

+0

Я полагаю, вы уже проверили Википедию и материал, на который они ссылаются, не так ли? –

+1

+1 Это отличная статья с очень важной информацией об этой проблеме. Один недостающий пункт: синхронизация удаленных записей. –

5

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

Наблюдение 1: знать о физических ударах, поскольку строки удаляются из исходного db, и вы должны делать то же самое на сервере db. Вы можете решить это, избегая физических удалений или протоколирования всех удалений в таблице с отметками времени. Что-то вроде этого: DeletedRows = (id, table_name, pk_column, pk_column_value, timestamp) Итак, вы должны прочитать все новые строки таблицы DeletedRows и выполнить удаление на сервере с помощью table_name, pk_column и pk_column_value.

Наблюдение 2: знать о FK, так как вставка данных в таблицу, которая связана с другой таблицей, может завершиться неудачей. Вы должны деактивировать каждый FK до синхронизации данных.

+1

часы должны быть синхронизированы – tofutim

4

Если кто-то имеет дело с аналогичной проблемой дизайна и нуждается в синхронизации изменений на нескольких устройствах Android, я рекомендую проверить Google Cloud Messaging for Android (GCM).

Я работаю над одним решением, в котором изменения, сделанные на одном клиенте, должны распространяться на других клиентов. И я только что реализовал доказательство реализации концепции (сервер & клиент), и это работает как шарм.

В принципе, каждый клиент отправляет изменения дельты на сервер. Например. Идентификатор ресурса ABCD1234 изменился со значения 100 на 99.

Сервер проверяет эти изменения дельты по своей базе данных и либо одобряет изменение (клиент находится в синхронизации), либо обновляет свою базу данных или отклоняет изменение (клиент не синхронизирован).

Если изменение одобрено сервером, сервер затем уведомляет других клиентов (за исключением тех, кто отправил изменение дельты) через GCM и отправляет многоадресное сообщение с тем же дельта-изменением. Клиенты обрабатывают это сообщение и обновляют свою базу данных.

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

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

Также проверьте this tutorial, чтобы начать реализацию клиента CGM.

2

это отвечает разработчикам, которые используют структуру Xamarin (см https://stackoverflow.com/questions/40156342/sync-online-offline-data)

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

Реализации довольно прост:

1) создать мобильное приложение в лазурном портале (вы можете попробовать его бесплатно здесь https://tryappservice.azure.com/)

2) подключить клиент к мобильному приложению. https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-xamarin-forms-get-started/

3) код для установки вашего локального репозитория:

const string path = "localrepository.db"; 

//Create our azure mobile app client 
this.MobileService = new MobileServiceClient("the api address as setup on Mobile app services in azure"); 

//setup our local sqlite store and initialize a table 
var repository = new MobileServiceSQLiteStore(path); 

// initialize a Foo table 
store.DefineTable<Foo>(); 

// init repository synchronisation 
await this.MobileService.SyncContext.InitializeAsync(repository); 
var fooTable = this.MobileService.GetSyncTable<Foo>(); 

4) затем нажать и тянуть свои данные, чтобы убедиться, что мы последние изменения:

await this.MobileService.SyncContext.PushAsync(); 
await this.saleItemsTable.PullAsync("allFoos", fooTable.CreateQuery()); 

https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-xamarin-forms-get-started-offline-data/

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