cron 时区陷阱 - 避免定时任务的漂移
以本地时间配置的 cron 任务在夏令时切换期间会静默地重复执行或跳过。本文详解其故障模式,介绍以 UTC 运行调度的方案、Kubernetes CronJob 的 timeZone 字段,以及云调度器如何处理同样的问题。
基里巴斯的莱恩群岛(UTC+14)最先迎来公历新年。它比日本早五个小时,这意味着当基里巴斯在庆祝时,日本还处于12月31日的19:00。最后迎来新年的是美国无人居住的贝克岛和豪兰岛(UTC-12),比基里巴斯晚26个小时。
地球上的每个时区都在这26小时的窗口内跨入新年。新西兰(UTC+12至+13)在基里巴斯之后1-2小时庆祝,澳大利亚东部(UTC+10至+11)再晚几个小时,日本晚5小时,欧洲晚13-14小时,纽约晚19小时,夏威夷晚24小时。这一推进过程是一场可以实时观看的全球仪式。
国际新闻直播跟随这波新年浪潮进行报道。悉尼海港大桥烟火(UTC+11)、东京新年寺庙钟声(UTC+9)、迪拜哈利法塔(UTC+4)、伦敦大本钟(UTC+0)和纽约时代广场(UTC-5)逐一展现在屏幕上,各标志性城市的倒计时接连上演。
观看这些报道能让人最直观地感受时区的真正含义。当悉尼庆祝午夜时,东京还是22:00,伦敦是13:00,纽约是8:00。同一时刻在不同地方承载着不同的日期和时间,这一事实从抽象的知识变成了生动可见的现实。
1月1日是公历新年,但世界上还存在许多其他新年。中国农历新年(春节)遵循阴阳历,落在1月下旬到2月中旬之间,全球约20%的人口庆祝这一节日。泰国的宋干节(4月13-15日)、伊朗的诺鲁孜节(3月20-21日,春分)以及犹太教的犹太新年(9-10月)都在不同的文化基础上标记新年。
埃塞俄比亚的新年Enkutatash在9月11日(闰年为12日),而埃塞俄比亚历比公历落后约7-8年。巴厘岛的尼耶皮节是萨卡历新年,又称“静默日”:全岛实行24小时宵禁并熄灯,这是世界上独一无二的以宁静方式庆祝新年的做法。
对于IT系统而言,真正的新年从1月1日UTC 00:00:00开始。年度批处理作业、日志轮转、证书过期和许可证续期都在UTC触发,与当地的庆祝活动无关。在日本,UTC午夜对应当地时间1月1日上午9点,因此日本工程师可能需要在元旦早晨监控系统。
2000年的千年虫问题不仅需要监控UTC午夜,还需要监控每个时区的午夜,因为潜在bug在各个时区可能以不同方式触发。全球运维团队守望了一场26小时的接力:基里巴斯最先通过,然后各地区依次跟进,每次安全通过都让下一个地区松一口气。千年虫最终平安度过,但那种贯穿所有时区的监控纪律是一次令人瞩目的全球工程演习。
在线游戏和全球直播需要选择对所有主要时区都合理的时间。UTC 12:00(正午)是一个常用的中心时间:东京为21:00,伦敦为12:00,纽约为7:00。所有主要市场都落在通常的清醒时段内,即使不全在工作时间内 - 这通常是单一固定UTC时间所能做到的最佳方案。
全球新年倒计时活动通常为每个地区安排各自当地午夜的开启时间。如果将开始时间固定在单一UTC时刻,某些地区会被迫在凌晨3点参与,引发公平性问题。按时区分别调度实现起来更复杂,但能显著提升全球社区的用户体验 - 人们不再觉得自己是各自庆典中的二等参与者。
这篇文章对您有帮助吗?
以本地时间配置的 cron 任务在夏令时切换期间会静默地重复执行或跳过。本文详解其故障模式,介绍以 UTC 运行调度的方案、Kubernetes CronJob 的 timeZone 字段,以及云调度器如何处理同样的问题。
了解时区如何将世界划分为不同本地时间的区域、UTC 偏移量的工作原理,以及为什么某些时区使用半小时增量。
软件中时间戳处理的首要法则是“以 UTC 存储,以本地时间显示”。本文介绍这一原则的理由、ISO 8601 格式、JavaScript 和 Python 中的实践模式、最常见的 bug,以及能在上线前捕获夏令时和日期线问题的测试策略。