Сегодня каждый может легко проверить текущее время множеством способов. У нас есть смартфоны, часы, компьютеры, ТВ, холодильники и так далее. Все знают, какой на дворе год, и что он означает. Мы разбираемся во временны́х зонах и знаем, что такое всемирное координированное время (UTC). Всё кажется таким тривиальным. Однако с точки зрения IT-систем здесь существует множество сюрпризов, вынуждающих нас сталкиваться с проблемами, которые возникают очень редко.
В различных IT-системах можно встретить множество нюансов, касающихся времени. Чаще всего они связаны с точностью его измерения и синхронизации между машинами в распределённых системах. В этой же статье я разберу одну странную ситуацию, которая за всю историю случалась лишь несколько раз.
▍ Високосная секунда
Изначально секунда была определена как 1/86400 доля суток. Затем в 1960 году её определение было изменено на 1/31 556 925,9747 долю тропического года. Однако оказалось, что Земля движется вокруг Солнца не всегда в точности одинаково, и иногда возникают отклонения от этого значения, вызываемые приливами, движением масс внутри планеты и землетрясениями. В связи с этим в 1967 году значение секунды было определено совершенно иным образом, а именно:
Как равное 9 192 631 770 периодам излучения, соответствующего переходу между двумя уровнями F = 3 и F = 4 основного состояния сверхтонкой структуры S1/2 атома цезия 133Cs.
Наиболее точными являются атомные часы, которые измеряют время на основе скорости прохождения электронов между двух оболочек атома. Однако остаётся вопрос компенсации разницы между значениями, измеряемыми атомными часами, и фактическим временем вращения Земли вокруг Солнца.
Для этого и была придумана «високосная секунда». День, когда нужно добавить эту секунду, определяет IERS (International Earth Rotation and Reference Systems Service, международная служба вращения Земли). Обычно она добавляется в последний день июня или декабря. Вычитание секунды тоже возможно, но на сегодня ещё ни разу не производилось.
История внесения високосных секунд:
- (+11 с) 30 июня, 1972
- (+12 с) 31 декабря, 1972
- (+13 с) 31 декабря, 1973
- (+14 с) 31 декабря, 1974
- (+15 с) 31 декабря, 1975
- (+16 с) 31 декабря, 1976
- (+17 с) 31 декабря, 1977
- (+18 с) 31 декабря, 1978
- (+19 с) 31 декабря, 1979
- (+20 с) 30 июня, 1981
- (+21 с) 30 июня, 1982
- (+22 с) 30 июня, 1983
- (+23 с) 30 июня, 1985
- (+24 с) 31 декабря, 1987
- (+25 с) 31 декабря, 1989
- (+26 с) 31 декабря, 1990
- (+27с) 30 июня, 1992
- (+28 с) 30 июня, 1993
- (+29 с) 30 июня, 1994
- (+30 с) 31 декабря, 1995
- (+31 с) 30 июня, 1997
- (+32 с) 31 декабря, 1998
- (+33 с) 31 декабря, 2005
- (+34 с) 31 декабря, 2008
- (+35 с) 30 июня, 2012
- (+36 с) 30 июня, 2015
- (+37 с) 31 декабря, 2016
▍ Время и IT-системы
Отслеживание времени используется в большинстве проектов. Нам нужна возможность отмечать время, когда произошло определённое действие пользователя, или когда было отправлено электронное письмо. Также бывает важно определять конкретный порядок событий. В случае одной машины это не особо сложно. А вот в распределённых системах, где мы имеем дело со множеством узлов, ситуация сильно усложняется.
Аппаратное время, устанавливаемое обычным тактовым генератором, не является абсолютно точным, и между узлами могут возникать различия. Когда для нас важна последовательность событий, расхождение в показаниях часов узлов становится неприемлемым. Для их синхронизации используется NTP (Network Time Protocol, протокол сетевого времени), который сопоставляет время конкретной машины со временем, указываемым группой серверов.
В компьютерах существует как минимум два вида часов: часы истинного времени и монотонные часы.
▍ Часы реального времени
Эти часы просто отображают фактическую дату и время. В системах Unix они опираются на дату 1 января 1970 года, 00:00:00, отсчитывая с этого момента количество прошедших секунд. Такие часы являются проблематичными, поскольку синхронизируются через NTP, который может заставить их перескакивать вперёд или назад. В связи с этим они недостаточно подходят для измерения пройденного времени, например, таймаутов.
▍ Монотонные часы
Монотонные часы более точны и предоставляют значения в микросекундах или даже более мелких единицах. Реализуются они в виде счётчиков, которые, например, могут начинать отсчёт при запуске системы. NTP в этом случае может корректировать только скорость отсчёта, замедляя или ускоряя конкретные часы. Поскольку перескакиваний в этом случае не происходит, такие часы лучше подходят для измерения пройденного времени.
▍ Последствия плохой синхронизации
Результатом недостаточной синхронизации расходящихся по времени часов может стать потеря данных. В этом случае лучше, когда система полностью падает, чем работает некорректно, что может привести к повреждению данных. Поэтому в ситуациях, когда мы опираемся на часы, они должны быть точно синхронизированы и отслеживаться. Если же часы работают некорректно, их нужно рассматривать как полностью неисправные.
▍ Порядок событий
К примеру, при репликации с несколькими ведущими узлами используется стратегия, при которой приоритет отдаётся последней операции записи. Поэтому если часы двух узлов будут рассинхронизированы, пусть даже на 2-3 мс, может измениться порядок записей, что приведёт к получению некорректных данных. Тем не менее по факту даже синхронизации с помощью NTP бывает недостаточно, поскольку в процессе работы также присутствуют сетевые задержки. В связи с этим для упорядочивания событий следует использовать логические часы на основе инкрементирования счётчика. Они не измеряют время, а лишь определяют относительный порядок событий.
В некоторых базах данных вроде Spanner от Google используется TrueTime API, возвращающий диапазон времени, которое может быть актуальным на данный момент (то есть с учётом возможной ошибки) — [самое раннее, самое позднее]. Такая база данных подобающим образом обрабатывает транзакции, затронутые этой ошибкой, обеспечивая тем самым правильный порядок событий. Естественно, чтобы добиться хорошей производительности, диапазон времени не должен быть слишком большим. Для этого Google в каждом из своих дата-центров для определения текущего времени использует GPS или атомные часы, что позволяет добиваться синхронизации с точностью до 7 мс.
Как видите, время в IT-системах является довольно непростой темой. Но мы с вами сосредоточимся на високосной секунде и проблемах, связанных именно с ней.
▍ Проблемы и сбои
Когда некое явление происходит редко, программисты понимают, что оно наверняка будет отличаться от их ожиданий, поскольку с ним ещё никто не сталкивался. В отношении високосных секунд подобная ситуация происходила 27 раз за 52 года, то есть в среднем она случается каждые два года. Это крайне редко, что ведёт к неизбежным проблемам и программным ошибкам. Самым сложным периодом оказался промежуток между 1999 и 2005 годами, когда о високосных секундах, по сути, просто забыли.
30 июня 2012 года на Reddit была зафиксирована значительная просадка быстродействия. Поначалу администраторы решили, что причина в замедлении сети, которое уже происходило несколькими днями ранее. Однако после более детального расследования выяснилось, что на машинах под управлением Linux очень сильно нагружаются процессоры. Проблема заключалась в ядре Linux — модуль
hrtimer
обезумел после того, как добавили лишнюю секунду. И коснулось это не только платформы Reddit, поскольку сбои заметили и другие компании. Линус Торвальдс прокомментировал ситуацию так:Практически каждый раз, когда мы добавляем високосную секунду, мы что-то обнаруживаем. Это реально раздражает, поскольку здесь у нас классический случай, когда мы имеем дело с кодом, который никогда не выполнялся, а значит не тестировался пользователями в типичных условиях.
▍ Объяснение проблемы hrtimer
Модуль
hrtimer
отвечает за вывод приложений из состояния ожидания. Имеются в виду приложения, которые ожидают, например, завершения выполнения операционной системой некоего задания, чтобы приступить к выполнению своего. Когда была добавлена високосная секунда, модуль сошёл с ума и пробудил все приложения, вызвав перегрузку процессора и сильное падение производительности, а иногда даже полный отказ системы.В случае Reddit проблема в основном повлияла на базу данных Cassandra и Java, в то время как аналогичные проблемы наблюдались в базах данных MySQL, на серверах Tomcat и платформе Hadoop.
Интересно, что за день до этого, когда операторы NTP объявили о добавлении високосной секунды, упали серверы Opera.
▍ Потребление энергии
Дата-центр Hetzner Online сообщил, что в ночь на 1 июля 2012 года значительно подскочило потребление энергии, превысив 1 мегаватт — вызвано это было описанным выше багом. Процессоры внезапно начали работать под 100% нагрузкой, что привело к повышению энергопотребления. На графике показано, что инцидент произошёл в 2:00 ночи, вероятно, из-за учёта временно́й зоны. Аналогичный скачок энергопотребления произошёл и в OVH. Скорее всего, подобная аномалия произошла и в других центрах, хотя сообщили о ней только эти два.
▍ Проблема 2000 года
Ещё несколько десятилетий назад мы и подумать не могли о такой роскоши, как практически безграничное использование памяти.
По этой причине год записывали, используя только две последние цифры. Первые проблемы начали возникать в 1990-х при определении, например, действительности кредитной карты, срок действия которой уходил в 2000-е годы. Многие люди говорили о катастрофе, которую это может вызвать — прогнозировали реальный апокалипсис. Конец света, конечно, не случился, но это всё же одна из глупейших ошибок программистов в истории. Очень опрометчиво брать в расчёт только недалёкое будущее. В конечном итоге приведение программного обеспечения в порядок потребовало много работы и, естественно, затрат.
▍ Варианты добавления високосной секунды
Простейшим способом является объявление серверами NTP о предстоящем добавлении високосной секунды. В итоге при её фактическом добавлении в конце минуты значение 59 отображается дважды.
Есть ещё один подход, который в основном используется в Windows и подразумевает просто игнорирование системой дополнительной секунды. В этом случае время переводится на корректное значение только при последующей синхронизации с NTP.
У обоих этих решений есть свои недостатки, поскольку в первом мы дублируем одно и то же время, а во втором сталкиваемся со странным переводом часов. Поэтому в Google решили подойти к этому вопросу иначе. Инженеры компании придумали альтернативное решение с «размазыванием секунды» на все 24 часа. Вместо единовременного добавления целой секунды оно подразумевает постепенное добавление миллисекунд в течение суток. Говоря точнее, к каждой секунде дня, в который должна быть добавлена високосная секунда, прибавляется значение 1/86400, получающееся в результате разделения одной секунды на все секунды суток, которых в них 24*60*60 = 86400.
▍ Возможные проблемы со временем в будущем
Следующая проблема может возникнуть 19 января 2038 года. В системах на базе Unix время хранится в виде количества секунд, прошедших с момента 00:00:00, 1 января 1970 года. Хранятся они в одной 32-битной целочисленной переменной, максимальное значение которой может достигать 2 147 483 647, что произойдёт 19 января 2038 года в 03:14:07. Решением этой проблемы будет переход на запись времени с помощью 64 бит, что значительно увеличит диапазон возможных значений (2^63-1). В этом случае следующая подобная проблема возникнет лишь в 292 277 026 596 году, то есть через 292 миллиарда лет. Операционные системы наверняка должным образом адаптируют, но, как известно, всегда найдётся тот, кто продолжит использовать старое недоработанное ПО и столкнётся с серьёзной проблемой.
▍ Отказ от високосной секунды
В результате многих лет дискуссий между различными органами по стандартизации в ноябре 2022 года на 27-й Генеральной конференции по мерам и весам было принято решение отказаться от високосной секунды к 2035 году или ранее. Начиная с 2035 года, дополнительные секунды перестанут быть проблемой. Международное бюро по мерам и весам разрешит отклонение UTC и UT1 до как минимум 2135 года в надежде, что учёные смогут выработать более эффективный метод учёта потерянного времени, или что компьютеры станут более совершенны в управлении его изменением.
▍ Итог
Как видите, оперировать временем не так просто, особенно в случае високосных секунд, когда фактическая работа того или иного решения в продакшене проверяется очень редко. Подобные проблемы неизбежно продолжат происходить, что не удивительно, так как это относительно низкоуровневые решения, которые используются во многих других продуктах. Тем не менее стоит признать, что наиболее предсказуемым и безопасным, похоже, является предложенный Google вариант с «размазыванием секунды». Он позволяет избежать неестественного скачка каждые X лет, применяя дополнительную секунду плавно без влияния на нормальную работу программ. Для тех, кому интересна тематика странностей, связанных со временем, рекомендую этот сайт.
P.S. В день добавления високосной секунды по возможности лучше отказаться от перемещений на самолёте и вообще оставаться дома. Что-то обязательно опять не будет работать — посмотрим, что на этот раз.
Telegram-канал со скидками, розыгрышами призов и новостями IT ?
Комментарии (33)
CitizenOfDreams
07.07.2024 12:50+2Непонятно, почему високосная секунда вызывает такие серьезные проблемы, а рутинная синхронизация набортных часов с серверами точного времени проходит без заметных последствий. В чем принципиальная разница?
funca
07.07.2024 12:50+2Все полагают, что секунды находятся в диапазоне 0...59. На самом деле он 0...60 из-за високосных секунд, но поведение софта в таких условиях мало кто проверяет.
Например, формула перевода дней в секунды: seconds = days*24*60*60 - в общем случае не верна, т.к. количество секунд зависит от конкретных дней в календаре. Однако вы этого не заметите, если не занимаетесь обработкой исторических данных, либо пока однажды в будущем часы не скорректируют ещё раз.
В истории так же был казус, связанный с гипотетической ситуацией, когда может добавиться сразу две високосные секунды. Из-за этого максимальным значением для секунд в python принято считать равным 61 https://bugs.python.org/issue2568.
Nick0las
07.07.2024 12:50Високосная секунда это просто какое-то торжество техники над здравым смыслом. Видимо авторы стандартов были очень горды, что человечество научилось мерять неравномерность вращения земли и придумали это усложнение.
Уход местного полдня мене чем на минуту за век не будет проблемой ни для кого. В бытовом смысле его не заметят, а у астрономов свой счет времени. А так писатели стандартов написали такой бред что преобразовать дату/время в будущем из HH:MM:SS в одно число - секунды от начала эпохи однозначно невозможно/
andy_p
07.07.2024 12:50+2Ошибаетесь. В астрономии, например, уход времени даже на несколько секунд означает, что вы опоздаете зафиксировать предсказанное событие. А так да, можно и 29 февраля отменить.
dimaaannn
07.07.2024 12:50+1Так пускай астрономы используют своё время, не привязанное к вращению какой то планетки?
Так то человек прав, 24 часовое время - условность. Собственно, как и даты. Учёные давным давно узнали что сутки - это не 24 часа, а год - не 365 дней по 24 часа. И всё равно продолжают жрать кактус, приправляя его переходами на летнее время.
Казалось бы - вот есть конкретная временная точка - 1 января 1970 года. Отсчитывай от неё в любую сторону, с любой необходимой точностью. Но нет, мы будем продолжать страдать, вносить поправки, синхронизироваться непонятно с чем, но не будем менять стандарт.
andy_p
07.07.2024 12:50Вы просто не в курсе. Ачтрономы и используют свое время, называется эфемеридное время. Проблема возникает тогда, когда надо перевести эфемеридное время в обычное, которым на Земле пользуются.
inkelyad
07.07.2024 12:50+1Проблема возникает тогда, когда надо перевести эфемеридное время в обычное, которым на Земле пользуются.
Переводить астрономическое время в гражданское нужно приблизительно только астрономам же? Которые этим и так вроде бы занимаются постоянно. И наличие високосных секунд в гражданском времени только головной боли в эти переводы добавлять должно.
andy_p
07.07.2024 12:50Еще можно с григорианского календаря вернуться на юлианский, он проще. Или вообще високосные года отменить, а то они только головной боли прибавляют. Правда тогда новый год на лето переедет, но это не беда
geher
07.07.2024 12:50У арабов он и переезжает постоянно. Причем это не один день в четыре года, а 10-12 дней каждый год. И ничего, никого у них там не парит.
andy_p
07.07.2024 12:50Конечно не парит. Если нет систем точного геопозиционирования, то какая разница, неделя туда, неделя сюда.
geher
07.07.2024 12:50А как наличие точного геопозиционирование связано с условным произвольным календарем? Системе геопозиционирования вне зависимости от точности как-то по барабану, новый год сегодня или нет. Все одно, пересчитывать время ко времени клиента с учетом всей этой лабуды с разными длинами месяцев, високосных годов (в арабском календаре они тоже есть, но по другому поводу), летним и поясным временем и прочими непотребствами человеческих календарей и местных особенностей отсчета времени..
andy_p
07.07.2024 12:50Системе геопозиционирования, действительно, по барабану, какой сейчас год, месяц или день, она живет по равномерному времени. Зато вам это не по барабану, потому, что ваша жизнь зависит от смены дня и ночи и времен года. Для того, чтобы ваша полночь не съехала на утро и вводятся високосные секунды.
Awerpol
07.07.2024 12:50В некоторых местах планеты ещё к метрической системе не перешли в быту, но в науке это основной стандарт. Аналогично можно вводить эфемеридное время для всё более широкого использования. А его даже в стандартных библиотеках яп наверняка нет
Nick0las
07.07.2024 12:50В астрономии в расчетах не используют UTC, и часто даже юлианский календарь используют. Так проще. Вообще для любых наблюдений за чем угодно плоское время (просто один счетчик единиц времени) удобней всех вариантов с секундами, часами, днями, месяцами потому что разницв во времени между двумя отсчетами можно вычислить в одну арифметическую операцию.
funca
07.07.2024 12:50+4Наука прекрасна тема, что в ней можно совершать грандиозные ошибки. За то теперь мы научились четко различать календарное время, которое связано с изменяющимися во времени (sic) величинами: местными традициями, скоростью вращения Земли и решениями глав отдельных государств. И абсолютное (monotonic time), которое не смотря ни на что нас все равно всех объединяет.
randomsimplenumber
07.07.2024 12:50абсолютное (monotonic time), которое не смотря ни на что
Вот, допустим,часы на марсоходе.. Что за время на них? Не ушло ли за время полета?
Nansch
07.07.2024 12:50по этому надо менять в наносекундах от начала эпохи и пользоваться этим в расчетах, а переводить в человеческие часы-минуты и обратно только при взаимодействии с пользователем.
Nick0las
07.07.2024 12:50Так все и стараются делать. Но проблемы есть:
По состоянию на сейчас невозможно написать корректный код перевода времени на будущее потому что когда добавят високосную секунду никто не знает.
Аппаратные RTC используют формат HH:MM:SS DD/MM/YY
bogolt
07.07.2024 12:50+1Хранятся они в одной 32-битной целочисленной переменной, максимальное
значение которой может достигать 2 147 483 647.....
Операционные системы наверняка должным образом адаптируютда как-бы давно уже все адаптировали.
printf("time_t size in bytes = %ld\n", sizeof(time_t));
выдает
time_t size in bytes = 8
Ну понятно что в каком-то роутере где до сих пор 32 битный линукс часы неправильно переведутся или в другом старом железе/ос. Но много ли такого железа доживет до 38 года?
Wesha
07.07.2024 12:50+4много ли такого железа доживет до 38 года?
Примерно тот же аргумент приводили в 1970 году.
bogolt
07.07.2024 12:50+1Простите не понял. Хранение даты как двух последних символов года это же чисто софтовое решение. Чтобы его исправить нужно лишь поменять код программы. Хранение даты как системного числа в типе time_t завязано на операционную систему. Это изменить намного сложнее и как правило требует перехода на 64 битный линукс, что требует перехода на 64 процессор. Поэтому в первом случае проблема никак не связана с железом.
Wesha
07.07.2024 12:50Хранение даты как двух последних символов года это же чисто софтовое решение.
По ссылке, я так понимаю, Вы не ходили. Речь вовсе не про "проблему 2000".
Это изменить намного сложнее и как правило требует перехода на 64 битный линукс, что требует перехода на 64 процессор.
Я уже понимаю, что Вы ничего в теме не понимаете. Разрядность чисел, с которыми работает компьютер, точно так же совершенно никак не связана с разрядностью процессора — я вполне могу написать программу для работы с 2048-битными числами для Z80. Поэтому "изменение разрядности [времени]" соверешенно не требует другого процессора — для этого точно так же "нужно лишь поменять код программы".
bogolt
07.07.2024 12:50+1я вполне могу написать программу для работы с 2048-битными числами для Z80
Но проблема-то в другом. Вам нужно будет переписать половину ядра системы потому что огромное количество системных функций будут ссылаться на системное время, а оно (удивление) будет завязано на системный time_t. Поэтому конечно если у вас какое-то свое приложение вы можете постараться и адаптировать его, но если мы хотим решить проблему целиком то самое простое это перевести все 32 битные линуксы на 64 битные.
По ссылке, я так понимаю, Вы не ходили. Речь вовсе не про "проблему 2000".
Я сходил по ссылке но почему-то решил что говорите о проблеме Y2K.
ptr128
07.07.2024 12:50Почему бы просто на ввести "цезиевое" время, не зависящее от вращения Земли и не требующее таких корректировок? А для отображения привычного нам времени просто хранить массив дат, когда добавлялась високосная секунда.
chnav
07.07.2024 12:50Непрерывная атомная шкала времени есть, можно покопаться на Хабре. Как минимум она используется в GPS. Но человеку неудобно работать с атомным временем, ему нужно HMS. Високосные секунды и призваны устранить этот недостаток - чтобы полдень оставался полднем.
CBET_TbMbI
Странно, откуда взялась проблема. В годе примерно 31,5 млн секунд. Секунда определена примерно 9 млрд периодами излучения. Разница более 2 порядков. Значит нет проблем так определить секунду, чтобы високосная секунда набегала не раз в год, а раз в век.
В 67-ом году неточно посчитали при назначении секунды?
Vpan
Вращение Земли вокруг своей оси замедляется, определить секунду так, чтобы високосная секунда набегала раз в век и эта схема действовала хотя бы несколько веков, невозможно.
CBET_TbMbI
Сутки как раз меняются очень мало. Около 2 мс за век, насколько помню.
Да, вот откопал https://habr.com/ru/articles/372959/
Это никак не объясняет, почему секунда определена так, что за сутки набегает 2-3 мс погрешности. Вращение Земли даёт такое замедление лишь за век.
Vpan
+2 лишние миллисекунды в сутках за век это много.
Эти две лишние миллисекунды в сутках по итогам года дадут разницу в 0,73 секунды (0,002 * 365). Вот и получаются ожидаемые 60-70 високосных секунд на протяжении века.
Почему секунда определена так, что прямо сейчас есть погрешность в 2-3 мс за сутки, не знаю. На мой взгляд, это и не важно: даже если переопределить секунду так, что в 21 веке "все будет хорошо", в 22 веке опять возникнут лишние 0,73 секунды за год и это бесконечная история.
ptr128
А теперь умножьте эти 2-3 мс на 365 и получите эту самую секунду за год.
avost
Проблема ведь не в точности определения секунды, а в "неточности" вращения Земли. "Линейка" кривая :).
Для 67-го года это было точное значение. Но с тех пор Земля замедлилась.
Переопределять секунду, подстраивая под вращение тоже плохая идея - секунда установлена как одна из опорных констант в системе измерений и если её менять поедут физические константы и значения. Именно поэтому её и зафиксировали с менее стабильного эталона на более стабильный (абсолютный в пределах текущих физических представлений).
CBET_TbMbI
История внесения високосных секунд говорит об обратном. Вначале приходилось добавлять високосную намного чаще, чем в 21 веке.
Возможно, тогда сделали расчёты замедления и выбрали секунду, которая будет средней в ближайший век. Но были ли тогда измерения и прогнозы столь точными...