Синхронизация клиент-серверных баз - PullRequest
76 голосов
/ 04 августа 2010

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

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

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

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

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

Ответы [ 5 ]

84 голосов
/ 06 августа 2010

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

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

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

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

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

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

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

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

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

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

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

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

С сайта Dr.Dobbs :

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

От arxiv.org:

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

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

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

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

5 голосов
/ 21 октября 2016

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

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

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

1) создайте мобильное приложение на портале Azure (вы можете попробовать его бесплатно здесь 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/

5 голосов
/ 16 января 2015

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

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

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

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

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

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

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

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

0 голосов
/ 06 июня 2018

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

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