Шаблон для синхронизации списков объектов среди компьютеров (в C ++)? - PullRequest
0 голосов
/ 18 сентября 2009

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

Это будет топология типа "звезда" - есть центральный мастер, а остальные - клиенты.

У меня действительно есть концепция сеанса, поэтому я могу хранить данные о каждом клиенте.

Есть ли хороший шаблон дизайна для этого? Еще лучше, есть ли (основанная на шаблонах) библиотека, которая будет обрабатывать запрос контейнера, что изменилось с тех пор, как пришел клиент X и получить эту дельту для отправки?

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

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

Это хорошо известный паттерн? Какие-либо дополнительные предложения?

Ответы [ 2 ]

1 голос
/ 18 сентября 2009

Способ реализации синхронизации во многом зависит от ваших потребностей. Нужно ли отправлять изменения клиентам или достаточно, чтобы клиенты проверяли, актуален ли объект, когда он использует эти объекты? Как насчет использования шаблона Proxy ? Этот шаблон позволяет вам создавать прокси-реализацию ваших объектов, которая может проверять их актуальность или нет, обновлять, если они не обновляются, и затем возвращать результат. Я бы сделал это, имея метку времени lastChanged для объектов на главном сервере и метку времени lastUpdated для клиентских объектов. Если задержка является проблемой, проверка актуальности объекта при каждом вызове, вероятно, не очень хорошая идея. Рассмотрите возможность создания отдельного потока, который запрашивает у мастера изменения объектов и помечает их как «грязные». Это также может значительно снизить сетевой трафик.

Вы также можете посмотреть шаблон Observer и Опубликовать / Подписаться .

0 голосов
/ 16 октября 2009

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

Способ, которым он будет работать, заключается в том, что каждый клиент будет генерировать "подпись" librsync своей локальной копии большого двоичного объекта и отправлять эту подпись мастеру. Подпись составляет около 1% от размера капли. Затем мастер будет использовать librsync для вычисления дельты между этой сигнатурой и текущими данными и отправит дельту клиенту, который будет использовать librsync для применения дельты к своей локальной копии большого двоичного объекта.

API librsync прост, а передача сигнатурных / дельта-данных относительно эффективна.

Если это нереализуемо, все же может быть полезно использовать более ручной «основанный на дельте» подход, чтобы избежать необходимости создания версий для каждого объекта. Каждый раз, когда мастер вносит изменения, он должен записывать эти изменения в журнал, записывая, что было сделано и с каким объектом. Управление версиями выполняется на уровне всей базы данных, поэтому каждой записи журнала присваивается номер версии.

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

...