Разрешение конфликтов для двусторонней синхронизации

24

Как вы управляете двусторонней синхронизацией между «основным» сервером базы данных и многими «вторичными» серверами, в частности разрешением конфликтов, при условии, что соединение не всегда доступно?

Например, у меня есть мобильное приложение, которое использует CoreData в качестве «базы данных» на iOS, и я хотел бы позволить пользователям редактировать содержимое без подключения к Интернету. В то же время эта информация доступна на веб-сайте, к которому будут подключаться устройства. Что мне делать, если / когда данные на двух серверах БД конфликтуют?
(Я называю CoreData сервером БД, хотя я знаю, что это немного другое.)

Существуют ли какие-либо общие стратегии для решения этой проблемы? Вот варианты, которые я могу придумать:
1. Всегда использовать данные на стороне клиента в качестве более высокого приоритета.
2. То же самое для стороны на сервере.
3. Попробуйте разрешить конфликты, отметив метку времени для каждого поля и выполнив последнее изменение.

Хотя я уверен, что третий вариант откроет место для разрушительного повреждения данных.

Я знаю, что теорема CAP касается этого, но мне нужна только возможная последовательность, поэтому она не исключает ее полностью, верно?

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

K.Steff
источник

Ответы:

14

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

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

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

Парсифаль
источник
1
Хорошо, это то, что я искал
K.Steff
10

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

DeadMG
источник
Хорошо, но как эти парни получают подобный эффект: развитие
Syncpoint
3
Они просто предполагают, что когда-нибудь в будущем у вас будет надежное соединение с достаточной пропускной способностью.
DeadMG
1

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

Я провел несколько симуляций, используя два устройства, компьютер и телефон, и электронную таблицу Google, чтобы проверить, как Google Docs автоматически обрабатывает конфликты. Вот несколько случаев:

Случай 1

  1. Компьютер и телефон отключены
  2. Компьютер отредактировал ячейку со значением «компьютер» и после телефона отредактировал ячейку со значением «телефон»
  3. Компьютер стал онлайн
  4. Телефон становится онлайн, и на компьютере и телефоне отображается «телефон».

Дело 2

  1. Компьютер и телефон отключены
  2. Компьютер отредактировал ячейку со значением «компьютер» и после телефона отредактировал ячейку со значением «телефон»
  3. Телефон стал онлайн
  4. Компьютер становится онлайн, и на компьютере, и на телефоне отображается «компьютер».

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

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

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

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

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

Аллан Велозо
источник
1
Я согласен, что подход к каждому конкретному случаю является подходящим способом пойти сюда. «Лучший» способ (подход git) не всегда применим, так как пользователи могут не захотеть просматривать / объединять изменения
K.Steff