Если вы запустите команду date на вашем (Unix) компьютере, вы увидите что-то вроде:
$ date Mon Nov 25 07:56:59 CET 2013
в вашем часовом поясе выбора. Это время происходит от аппаратной части, локальной для вашей машины, встроенной где-то на материнской плате и обычно работающей от батареи BIOS. Чем больше ваша система, тем сложнее будет определить текущее время.
Часы дрейфуют
Время, считываемое по дате, называется системным временем; оно отделено от фактического времени, считываемого с аппаратных часов во время загрузки, и передается при каждом прерывании таймера, создаваемом специализированной схемой. Это время может даже быть в разных часовых поясах: вы можете установить системное время в часовой пояс вашей страны, сохраняя аппаратные часы в UTC.
hwclock запросит у вас аппаратные часы:
$ hwclock Wed 06 Nov 2013 02:12:28 PM CET -0.287960 seconds
Выполнение той же команды с параметрами отладки немного объясняет, как работают часы:
$ hwclock --debug hwclock from util-linux-ng 2.17.2 Using /dev interface to clock. Assuming hardware clock is kept in local time. Waiting for clock tick... ...got clock tick Time read from Hardware Clock: 2013/11/06 14:13:24 Hw clock time : 2013/11/06 14:13:24 = 1383743604 seconds since 1969 Wed 06 Nov 2013 02:13:24 PM CET -0.450946 seconds
Я выполнил эту команду на виртуальной машине, которая находилась в спящем режиме в течение нескольких недель, поэтому вы можете видеть, что время застревало на всех интервалах, в течение которых машина сохранялась на диске. Запуск того же на физической машине дает:
$ hwclock --debug hwclock from util-linux-ng 2.17.2 Using /dev interface to clock. Assuming hardware clock is kept in local time. Waiting for clock tick... ...got clock tick Time read from Hardware Clock: 2013/11/06 14:13:24 Hw clock time : 2013/11/06 14:13:24 = 1383743604 seconds since 1969 Wed 06 Nov 2013 02:13:24 PM CET -0.450946 seconds
Часы идут через тики, которые происходят с фиксированной частотой, такой как 4000 Гц. Этот тик принимается ядром, которое соответственно увеличивает свое время. Тем не менее, частота прерывания устанавливается только с допуском.
Фактически, различное оборудование с одинаковыми характеристиками показывает тактовые импульсы, происходящие с очень похожей частотой, но не идентичные. Учитывая эталонные, очень точные часы, такие как сервер времени, величина, на которой другая машина дистанцируется от эталона, называется дрейфом часов; обычно оно пропорционально времени от последней корректировки.
Введите NTP
NTP — это протокол, который выполняет автоматическую настройку времени компьютера, поддерживая на нем демон (ntpd на машинах Unix) и опрашивая внешние серверы времени. Серверы времени управляются статистическими институтами (IEN в моей стране), которые подключают машины к точным аппаратным средствам, таким как атомные часы, например, те, которые работают на спутниках GPS.
Полное описание протокола может представлять собой небольшую отдельную книгу, но она работает примерно так:
- локальная система A знает, что ее часы дрейфуют, и отправляет исходящий пакет на сервер времени B, отмечая его A1.
- сервер времени B отвечает другим пакетом, отмеченным реальным временем B1.
- А получает этот пакет в местное время А2.
- A теперь знает, что реальное время в A1 + (A2-A1) / 2, при условии симметричной задержки, было B1. Он может настроить свои часы, чтобы соответствовать в B1 + (A2-A1) / 2.
(на самом деле маркеры являются более сложными: сервер имеет отметки времени B1 и B2 приема пакета и передачи ответа. Кроме того, процесс повторяется, и его результаты статистически анализируются. NTP также отличается сложностью в виде уровней серверов, но мы не собираемся туда.)
Мы хотим сосредоточиться только на последнем этапе: корректировка. Часы под управлением NTP могут настраиваться, особенно при высокой нагрузке, на секунды или десятки секунд.
Это означает, что в вашей базе данных вы можете регистрировать такие события, как:
- сообщение (1, in_response_to = NULL, текст = …, созданный_ат = 14: 13: 24)
- сообщение (2, in_response_to = 1, текст = …, созданный_ат = 14: 13: 22)
что может осложнить вашу жизнь, когда клиент спрашивает, как возможно, что ответ был создан перед вопросом. Они сказали, что программирование — это легкая работа, верно? Этот сценарий может произойти, особенно когда сообщения генерируются не людьми, а автоматизированными процессами.
Несколько серверов
Причина, по которой NTP так широко используется, заключается в том, чтобы синхронизировать парк серверов с одним источником времени. Даже в этом случае система не идеальна, поскольку каждая машина работает в соответствии со своими локальными аппаратными часами.
Даже если все часы медленнее эталонного и показывают задержку относительно источника, описанная выше ситуация все же возможна из-за относительного отличия от машин. Предположим, что реальное время 14:13:25, когда 1 и 2 вставлены последовательно, но на разных серверах:
- message (1, in_response_to = NULL, text = …, creation_at = 14: 13: 24) // машина с более медленным тактовым сигналом относительно источника
- message (2, in_response_to = 1, text = …, creation_at = 14: 13: 22) // машина с более медленным тактом по сравнению с другим
Создание времени генерации базы данных решает проблему только до тех пор, пока для записи требуется более одного компьютера, и это компенсирует тестируемость кода, который зависит от времени, которое теперь зависит от базы данных.
Решительным решением является запрос времени у централизованного сервера, который вносит задержку и становится единственной точкой отказа (и все еще подвергается корректировкам). Более прагматичное решение — указать, что все моменты времени, собранные приложением, если они не чувствительны, имеют 10-секундный допуск.
Выводы
Время — сложное понятие: неудивительно, что несколько тысячелетий прошло с зари цивилизации до того момента, когда мы приобрели инструменты, достаточно точные для измерения секунд и миллисекунд (вспомним песочные часы). Небольшие ошибки накапливаются до тех пор, пока точные часы не сместятся друг с другом и не потребуются постоянные обновления; что является проблемой с распределенными системами и необходимость допусков раздела …