Синхронизация клиент-серверных баз данных


85

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

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

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

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

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

Ответы:


96

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

То есть: предположим, что запись № 125 была изменена на сервере 5 января в 22:00, и такая же запись была изменена на одном из телефонов (назовем ее клиентом A) 5 января в 23:00. Последняя синхронизация была 3 января. Затем пользователь снова подключается, скажем, 8 января.

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

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

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

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

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

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

Подводя итог, можно выделить следующие основные проблемы:

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

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

  • Подробнее об этом, конечно же, в Википедии .

  • Простой алгоритм синхронизации от автора Vdirsyncer

  • Статья OBJC о синхронизации данных

  • SyncML®: синхронизация и управление мобильными данными (Книга в O'Reilly Safari)

  • Бесконфликтные реплицированные типы данных

  • Оптимистическая репликация ЯСУШИ САЙТО (HP Laboratories) и МАРК ШАПИРО (Microsoft Research Ltd.) - ACM Computing Surveys, Vol. V, № N, 3, 2005.

  • Александр Трауд, Юрген Наглер-Ихляйн, Франк Каргл и Майкл Вебер. 2008. Циклическая синхронизация данных посредством повторного использования SyncML. В материалах Девятой Международной конференции по управлению мобильными данными (MDM '08). IEEE Computer Society, Вашингтон, округ Колумбия, США, 165–172. DOI = 10.1109 / MDM.2008.10 http://dx.doi.org/10.1109/MDM.2008.10

  • Лам Ф., Лам Н. и Вонг Р. 2002. Эффективная синхронизация мобильных XML-данных. В материалах одиннадцатой международной конференции по управлению информацией и знаниями (Маклин, Вирджиния, США, 4–9 ноября 2002 г.). ЦИКМ '02. ACM, Нью-Йорк, Нью-Йорк, 153–160. DOI = http://doi.acm.org/10.1145/584792.584820

  • Cunha, PR и Maibaum, TS 1981. Resource & equil; абстрактный тип данных + синхронизация - Методология программирования, ориентированного на сообщения -. В материалах 5-й международной конференции по разработке программного обеспечения (Сан-Диего, Калифорния, США, 9–12 марта 1981 г.). Международная конференция по программной инженерии. IEEE Press, Пискатауэй, Нью-Джерси, 263-272.

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

С сайта доктора Доббса :

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

С arxiv.org:

  • Бесконфликтный реплицированный тип данных JSON - в документе описывается реализация JSON CRDT (бесконфликтные реплицированные типы данных - CRDT - это семейство структур данных, которые поддерживают одновременное изменение и гарантируют конвергенцию таких одновременных обновлений).

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

Я полагаю, вы уже проверили Википедию и все, на что они ссылаются, верно?
p.marino 06

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

7
Я склонен рассматривать «удаленный» как частный случай «обновленного», особенно потому, что для такого рода ситуаций я предпочитаю «логическое удаление» вместо «физического удаления». Так что для меня «удаленный» на стороне ведущего или ведомого означает «перевернут специальный логический флаг is-удален» больше, чем что-либо еще.
p.marino

Благодарю. Я добавил еще одну ссылку на другую статью (dr.dobbs) и обновлю библиографию, если найду что-нибудь еще.
p.marino

9

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

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

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


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

6

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

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

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

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

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

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

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

Также ознакомьтесь с этим руководством, чтобы начать работу с реализацией клиента CGM.


5

это отвечает разработчикам, использующим платформу Xamarin (см. /programming/40156342/sync-online-offline-data )

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

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

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/


0

Предлагаю вам также взглянуть на Симметрики . это библиотека репликации SQLite, доступная для систем Android. вы можете использовать его для синхронизации базы данных клиента и сервера, я также предлагаю иметь отдельные базы данных на сервере для каждого клиента. Попытка хранить данные всех пользователей в одной базе данных mysql - не всегда лучшая идея. Особенно, если объем пользовательских данных будет быстро расти.


0

Назовем это проблемой CUDR Sync (мне не нравится CRUD, потому что Create / Update / Delete записываются и должны быть соединены вместе)

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

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

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

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


Далее запись отсутствует подход будет иметь проблемы на приложение удаления, все данные не загружено онлайн будут удалены
DragonFire
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.