Сегодня каждый может легко проверить текущее время множеством способов. У нас есть смартфоны, часы, компьютеры, ТВ, холодильники и так далее. Все знают, какой на дворе год, и что он означает. Мы разбираемся во временны́х зонах и знаем, что такое всемирное координированное время (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, международная служба вращения Земли). Обычно она добавляется в последний день июня или декабря. Вычитание секунды тоже возможно, но на сегодня ещё ни разу не производилось.

История внесения високосных секунд:

  1. (+11 с) 30 июня, 1972
  2. (+12 с) 31 декабря, 1972
  3. (+13 с) 31 декабря, 1973
  4. (+14 с) 31 декабря, 1974
  5. (+15 с) 31 декабря, 1975
  6. (+16 с) 31 декабря, 1976
  7. (+17 с) 31 декабря, 1977
  8. (+18 с) 31 декабря, 1978
  9. (+19 с) 31 декабря, 1979
  10. (+20 с) 30 июня, 1981
  11. (+21 с) 30 июня, 1982
  12. (+22 с) 30 июня, 1983
  13. (+23 с) 30 июня, 1985
  14. (+24 с) 31 декабря, 1987
  15. (+25 с) 31 декабря, 1989
  16. (+26 с) 31 декабря, 1990
  17. (+27с) 30 июня, 1992
  18. (+28 с) 30 июня, 1993
  19. (+29 с) 30 июня, 1994
  20. (+30 с) 31 декабря, 1995
  21. (+31 с) 30 июня, 1997
  22. (+32 с) 31 декабря, 1998
  23. (+33 с) 31 декабря, 2005
  24. (+34 с) 31 декабря, 2008
  25. (+35 с) 30 июня, 2012
  26. (+36 с) 30 июня, 2015
  27. (+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 ?

Комментарии (20)


  1. CBET_TbMbI
    07.07.2024 12:50

    Странно, откуда взялась проблема. В годе примерно 31,5 млн секунд. Секунда определена примерно 9 млрд периодами излучения. Разница более 2 порядков. Значит нет проблем так определить секунду, чтобы високосная секунда набегала не раз в год, а раз в век.

    В 67-ом году неточно посчитали при назначении секунды?


    1. Vpan
      07.07.2024 12:50
      +4

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


      1. CBET_TbMbI
        07.07.2024 12:50

        Сутки как раз меняются очень мало. Около 2 мс за век, насколько помню.

        Да, вот откопал https://habr.com/ru/articles/372959/

        Это никак не объясняет, почему секунда определена так, что за сутки набегает 2-3 мс погрешности. Вращение Земли даёт такое замедление лишь за век.


        1. Vpan
          07.07.2024 12:50
          +1

          +2 лишние миллисекунды в сутках за век это много.

          Эти две лишние миллисекунды в сутках по итогам года дадут разницу в 0,73 секунды (0,002 * 365). Вот и получаются ожидаемые 60-70 високосных секунд на протяжении века.

          Почему секунда определена так, что прямо сейчас есть погрешность в 2-3 мс за сутки, не знаю. На мой взгляд, это и не важно: даже если переопределить секунду так, что в 21 веке "все будет хорошо", в 22 веке опять возникнут лишние 0,73 секунды за год и это бесконечная история.


    1. avost
      07.07.2024 12:50
      +2

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

      Проблема ведь не в точности определения секунды, а в "неточности" вращения Земли. "Линейка" кривая :).

      В 67-ом году неточно посчитали при назначении секунды?

      Для 67-го года это было точное значение. Но с тех пор Земля замедлилась.

      Переопределять секунду, подстраивая под вращение тоже плохая идея - секунда установлена как одна из опорных констант в системе измерений и если её менять поедут физические константы и значения. Именно поэтому её и зафиксировали с менее стабильного эталона на более стабильный (абсолютный в пределах текущих физических представлений).


      1. CBET_TbMbI
        07.07.2024 12:50

        Для 67-го года это было точное значение. Но с тех пор Земля замедлилась.

        История внесения високосных секунд говорит об обратном. Вначале приходилось добавлять високосную намного чаще, чем в 21 веке.

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


  1. CitizenOfDreams
    07.07.2024 12:50
    +2

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


    1. funca
      07.07.2024 12:50
      +1

      Все полагают, что секунды находятся в диапазоне 0...59. На самом деле он 0...60 из-за високосных секунд, но поведение софта в таких условиях мало кто проверяет.

      Например, формула перевода дней в секунды: seconds = days*24*60*60 - в общем случае не верна, т.к. количество секунд зависит от конкретных дней в календаре. Однако вы этого не заметите, если не занимаетесь обработкой исторических данных, либо пока однажды в будущем часы не скорректируют ещё раз.

      В истории так же был казус, связанный с гипотетической ситуацией, когда может добавиться сразу две високосные секунды. Из-за этого максимальным значением для секунд в python принято считать равным 61 https://bugs.python.org/issue2568.


  1. Nick0las
    07.07.2024 12:50

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

    Уход местного полдня мене чем на минуту за век не будет проблемой ни для кого. В бытовом смысле его не заметят, а у астрономов свой счет времени. А так писатели стандартов написали такой бред что преобразовать дату/время в будущем из HH:MM:SS в одно число - секунды от начала эпохи однозначно невозможно/


    1. andy_p
      07.07.2024 12:50
      +2

      Ошибаетесь. В астрономии, например, уход времени даже на несколько секунд означает, что вы опоздаете зафиксировать предсказанное событие. А так да, можно и 29 февраля отменить.


      1. dimaaannn
        07.07.2024 12:50

        Так пускай астрономы используют своё время, не привязанное к вращению какой то планетки?

        Так то человек прав, 24 часовое время - условность. Собственно, как и даты. Учёные давным давно узнали что сутки - это не 24 часа, а год - не 365 дней по 24 часа. И всё равно продолжают жрать кактус, приправляя его переходами на летнее время.

        Казалось бы - вот есть конкретная временная точка - 1 января 1970 года. Отсчитывай от неё в любую сторону, с любой необходимой точностью. Но нет, мы будем продолжать страдать, вносить поправки, синхронизироваться непонятно с чем, но не будем менять стандарт.


        1. andy_p
          07.07.2024 12:50

          Вы просто не в курсе. Ачтрономы и используют свое время, называется эфемеридное время. Проблема возникает тогда, когда надо перевести эфемеридное время в обычное, которым на Земле пользуются.


          1. inkelyad
            07.07.2024 12:50

            Проблема возникает тогда, когда надо перевести эфемеридное время в обычное, которым на Земле пользуются.

            Переводить астрономическое время в гражданское нужно приблизительно только астрономам же? Которые этим и так вроде бы занимаются постоянно. И наличие високосных секунд в гражданском времени только головной боли в эти переводы добавлять должно.


            1. andy_p
              07.07.2024 12:50

              Еще можно с григорианского календаря вернуться на юлианский, он проще. Или вообще високосные года отменить, а то они только головной боли прибавляют. Правда тогда новый год на лето переедет, но это не беда


              1. geher
                07.07.2024 12:50

                У арабов он и переезжает постоянно. Причем это не один день в четыре года, а 10-12 дней каждый год. И ничего, никого у них там не парит.


                1. andy_p
                  07.07.2024 12:50

                  Конечно не парит. Если нет систем точного геопозиционирования, то какая разница, неделя туда, неделя сюда.


                  1. geher
                    07.07.2024 12:50

                    А как наличие точного геопозиционирование связано с условным произвольным календарем? Системе геопозиционирования вне зависимости от точности как-то по барабану, новый год сегодня или нет. Все одно, пересчитывать время ко времени клиента с учетом всей этой лабуды с разными длинами месяцев, високосных годов (в арабском календаре они тоже есть, но по другому поводу), летним и поясным временем и прочими непотребствами человеческих календарей и местных особенностей отсчета времени..


    1. funca
      07.07.2024 12:50
      +2

      Наука прекрасна тема, что в ней можно совершать грандиозные ошибки. За то теперь мы научились четко различать календарное время, которое связано с изменяющимися во времени (sic) величинами: местными традициями, скоростью вращения Земли и решениями глав отдельных государств. И абсолютное (monotonic time), которое не смотря ни на что нас все равно всех объединяет.


  1. bogolt
    07.07.2024 12:50

    Хранятся они в одной 32-битной целочисленной переменной, максимальное
    значение которой может достигать 2 147 483 647.....
    Операционные системы наверняка должным образом адаптируют

    да как-бы давно уже все адаптировали.

    printf("time_t size in bytes = %ld\n", sizeof(time_t));

    выдает time_t size in bytes = 8

    Ну понятно что в каком-то роутере где до сих пор 32 битный линукс часы неправильно переведутся или в другом старом железе/ос. Но много ли такого железа доживет до 38 года?


    1. Wesha
      07.07.2024 12:50

      много ли такого железа доживет до 38 года?

      Примерно тот же аргумент приводили в 1970 году.