Синхронизация (часов) между двумя удаленными компьютерами

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

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

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

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

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

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

Ответ 1

Опираясь на NTP для вашего приложения, как рекомендовали другие, это просто выдумка. Правильный подход заключается в использовании алгоритма синхронизации распределенных часов Lamport. Это объясняется в его классической статье 1978 Время, часы и порядок событий в распределенной системе.

Ответ 3

Вы можете попробовать PTP, протокол Precision Time Protocol (PTP) - это протокол, используемый для синхронизации часов в компьютерной сети. В локальной сети достигается точность тактовой частоты в субмикросекундах, что делает ее пригодной для систем измерения и управления. http://en.wikipedia.org/wiki/Precision_Time_Protocol

Ответ 4

Синхронизировать их с NTP Протокол сетевого времени.

На какой платформе вы работаете?

С помощью NTP вы можете синхронизировать время своих компьютеров с атомными часами и использовать официальное время в мире.

Ответ 5

Вместо того, чтобы писать код для синхронизации часов, не удалось бы просто запустить клиент ntp на обеих машинах?

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

Ответ 6

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

1) Не хватает вычислительных знаний, чтобы настроить синхронизацию времени ntp

2) Установите часы своего компьютера на часы дома или часы мобильного телефона, которые являются неправильными

3) В Windows XP случайно отключить синхронизацию времени ntp и не знать, как ее включить, или установить неверную дату компьютера, и в этом случае Windows ntp не работает.

4) Батарея компьютера компьютера разрядилась, поэтому компьютер всегда запускается в 1970 году.

5) Пользователь берет свой ноутбук за границей и временно устанавливает часы ноутбука в местное время, но не меняет часовой пояс, поэтому теперь ПК вернет неправильное время utc!!!

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

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

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

1) Когда ваше приложение запускается, оно синхронизирует свое собственное внутреннее время utc с ntp посредством вызова мыла на стороннем сервере или на вашем собственном сервере времени (который вы можете сами провести с ntp).

2) После этого он добавляет по истечении времени от системных часов для поддержания времени. Если требования строгие, вам может потребоваться повторить синхронизацию ntp с интервалами.

3) Затем приложение просматривает список будущих заданий, которые необходимо выполнить вовремя. Он должен знать самую раннюю работу.

4) Затем он создает поток, который он засыпает в течение времени, предшествующего самому раннему заданию, за вычетом резерва безопасности, который в зависимости от ваших требований может составлять 10 минут вперед, час или два заранее и т.д..

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

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

Усовершенствования идеи:

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

2) Ваше приложение может добавлять новые, более ранние задания "на лету" или удалять задания, поэтому ваш спальный поток, вероятно, должен быть пробужден для пересчета для нового более раннего задания или для задания, следующего за удаленным заданием. В Win32 вы сделали бы это своим потоком, ожидающим с таймаутом на Событии, который вы задали, чтобы заставить его пересчитать время сна. В Linux нет сомнений, что существует аналогичный механизм.

3) Для вызова мыла, чтобы получить время, обратите внимание, когда мыло отправлено и когда получен ответ. Если время обработки слишком велико, вы не можете полагаться на время и, возможно, придется повторять вызов, иначе вы можете пойти на компромисс. Например, если мыло говорит, что компьютерные часы на 5 минут быстрее, но сам вызов мыла занял минуту, чтобы ответить, тогда вы можете только сказать наверняка, что часы компьютера не менее 4 минут быстро.

Ответ 7

Одна вещь, которую мы делаем, - это, по сути, разгрузить все операции синхронизации на машину "хозяин". Например, если у вас есть 20 серверов, которые используют общий доступ к базе данных, используйте время DB. Если у вас есть центральный сервер и миллион клиентских машин, тогда клиентские машины не должны нести ответственность за синхронизацию чего-либо; сделайте всю вашу синхронизацию на стороне сервера. В действительно "распределенной" среде, такой как сеть P2P или что-то в этом роде, используйте машину, которая наиболее непосредственно "владеет" рассматриваемым ресурсом (фактический ПК, файл, который вы хотите записать), чтобы синхронизировать/контролировать доступ к файлу.

Ответ 8

любая сетевая машина должна использовать NTP. все современные системы включают в себя простой способ настройки. единственная проблема должна заключаться в выборе конкретного сервера, если вам нужна небольшая дополнительная точность; но это уже в миллисекундах, поэтому мне все равно, и обычно просто укажу на pool.ntp.org

Ответ 9

Не используйте NTP. NTP предназначен только для получения даты/времени.

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

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