2009-08-12 6 views
13

У меня есть интернет-приложение, которое поддерживает автономный режим, когда пользователи могут создавать данные, которые будут синхронизироваться с сервером, когда пользователь вернется в онлайновом режиме. Поэтому из-за этого я использую UUID для идентификации в моей базе данных, поэтому отключенные клиенты могут создавать новые объекты, не опасаясь использовать идентификатор, используемый другим клиентом, и т. Д. Однако, хотя это отлично подходит для объектов, принадлежащих этому пользователю, являются объектами, которые совместно используются несколькими пользователями. Например, теги, используемые пользователем, могут быть глобальными, и нет возможности, чтобы удаленная база данных могла хранить все возможные теги во Вселенной.Лучшая практика для синхронизации распространенных распределенных данных

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

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

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

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

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

Так что я ищу какое-либо наилучшую практику, существующие алгоритмы для обработки этого типа системы, руководство по выбору и т.д.

+0

Я знаю, что этот вопрос составляет около 6 лет. Я столкнулся в основном с той же ситуацией. Любопытно, если ваше время + опыт на эту тему дал вам дополнительную информацию? Название тега как естественный ключ кажется хорошим выбором. Как использование UUID спросило, что ваши основные ключи работают? –

ответ

2

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

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

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

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

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

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

3

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

+0

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

+0

Да, ты прав. Если вы не можете запускать CouchDB с обоих концов, нет никакого преимущества. Жалость. – Evan

+1

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

4

В зависимости от того, какую семантику приложения вы хотите предложить пользователям, вы можете выбрать различные решения. Например, если вы на самом деле говорите об объектах тегирования, созданных автономным пользователем с ключевым словом, и хотите поделиться тегами между несколькими объектами, созданными разными пользователями, то использование текста для тега прекрасное, как вы предложили. Когда все изменения будут объединены, теги с одним и тем же «текстом», например, говорят «ЭТО УДИВИТЕЛЬНО», будут разделены.

Существуют и другие способы обработки отключенных обновлений для общих объектов. SVN, CVS и другая система управления версиями пытаются разрешить конфликты автоматически, а когда не могут, просто скажут пользователю, что есть конфликт. Вы можете сделать то же самое, просто сообщите пользователю, что были параллельные обновления, и пользователям приходится обрабатывать разрешение.

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

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

Несколько вариантов. Надеюсь это поможет.

+1

Я часто вижу, что люди ссылаются на SVN, CVS и т. Д. В качестве примеров синхронизации, но нет реальной предметной дискуссии о том, как они это делают. Как они вычисляют различия в больших масштабах? Как они отслеживают, что изменилось с момента последней синхронизации? В какой-то степени я думаю, что CVS и SVN неприменимы. SVN напрямую не обрабатывает ситуации, когда я создаю файл, а другой пользователь создает файл с тем же именем. Пользователь должен решить путем слияния. В моем случае мне нужно быть более изящным, потому что его старый тег не совпадает с идентификатором, указанным в удаленном хранилище. SVN не является графом объектов. Нет смены идентификаторов. – chubbsondubs

+0

Требование к вашему приложению важно. Вы можете посмотреть файловую систему Coda и другие известные техники. Я думаю, у вас есть 3 варианта. Вариант 1: попросите пользователя помочь объединить конфликты и состояние приложения очистки. Вариант 2: всегда разрешать параллельные операции. Например. используя глобально уникальные идентификаторы для новых файлов, но позволяют пользователям создавать файлы с тем же именем в одном и том же общем каталоге. Вариант 3: автоматически разбивается на две ветви/версии объекта при одновременных обновлениях. Пользователь может объединять ветви всякий раз, но до слияния внутреннее состояние приложения «согласовано». – OverClocked

+0

Я был бы счастлив, если бы вы описали больше того, что вы пытаетесь сделать ... – OverClocked

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

  • Нет связанных вопросов^_^