clock realtime 与 clock monotonic

clock realtime

代表机器上可以理解为当前的我们所常看的时间,其当time-of-day 被修改的时候而改变,这包括NTP对它的修改(NTP:Network Time Protocol(NTP)是用来使计算机时间同步化的一种协议,它可以使计算机对其服务器或时钟源(如石英钟,GPS等等)做同步化,它可以提供高精准度的时间校正(LAN上与标准间差小于1毫秒,WAN上几十毫秒),且可介由加密确认的方式来防止恶毒的协议攻击。)

clock monotonic

代表从过去某个固定的时间点开始的绝对的逝去时间,它不受任何系统time-of-day时钟修改的影响,如果你想计算出在一台计算机上不受重启的影响,两个事件发生的间隔时间的话,那么它将是最好的选择。


社区摘录的文章

  • 假设你想知道一个事件花费了多少时间。你记录下开始时间,然后开始运行事件,再记录下结束时间,然后再使用结束时间减去开始时间。如果事件花费了10 毫秒,那么两项时间的相减结果就是10毫秒,当然可能存在很小的误差。
start := time.Now()       // 3:04:05.000 开始时间
event()
end := time.Now()         // 3:04:05.010 结束时间

elapsed := end.Sub(start) // 10 ms  耗时10毫秒
  • 上面这个使用两个时间相减的方法在闰秒期间会失败。当我们的时钟与地球日常旋转不同步时,在午夜之前插入闰秒,即 11:59 分 60 秒。与闰年不同,闰秒没有可以预见的模式,这个特性使闰秒很难使用应用程序和接口。操作系统通常不会尝试表示偶尔才出现的 61 秒的时间,取而代之的是操作系统通常会在午夜到来前将时间倒退 1 秒,所以下午 11:59 分 59 秒会出现两次。这个时钟复位使时间看起来向后移动,所以我们的 10 毫秒的事件处理时间可能是 -990 毫秒 。
start := time.Now()       // 11:59:59.995 开始时间
event()
end := time.Now()         // 11:59:59.005 (really 11:59:60.005) 结束时间

elapsed := end.Sub(start) // –990 ms 耗时-990毫秒, 实际耗时10毫秒,由于闰秒,OS出现两次11:59:59,结束时间小于开始时间
  • 正因为用来时间复位和时间事件的 time-of-day clock 不准确,操作系统现在提供第二个时钟,monotonic clock ,它没有绝对的意义,只是用来计秒,并永远不会重置。

  • 除了在奇时钟复位方面,monotonic clock 并不比 time-of-day clock 更好,而且 time-of-day clock 还具有用于告知时间的额外优势,因此在简单的 Go 1 time API 中仅公开了 time-of-day clock 。

  • 2015 年 10 月,有用户反馈了一个 Go 程序无法在时钟重置时间内正确运行事件的 bug ,尤其是典型的闰秒。建议的修复方法是:“添加一个新的 API 来访问 monotonic clock 资源”。我认为这个问题不足以证明我们需要新的 API 。几个月前,Akamai、亚马逊和谷歌将他们的时钟放慢了一点,添加了额外的秒数,来解决闰秒的问题。而且大家最终都倾向于采用这种“闰秒弥补”来应对“闰秒”问题。向 Go 添加新的 API 会带来新的问题:我们必须解释两种时钟,并指导用户何时使用它们,并转换许多行现有的代码。

  • 当没有明确的解决问题的方案出现时,我们唯一能做的就是:等待。等待给我们更多的时间来积累经验并加深理解,以及有更充足的实际去寻找一个良好的解决方案。正因如此,等待加深了我们对这个问题的理解,Cloudflare 的一次轻微中断事故触发了我们的灵感。他们的 Go 代码在2016年底的闰秒期间定时 DNS 请求耗时达到 990 毫秒,导致其服务器同时出现问题,影响了峰值期间 0.2% 的 DNS 查询。

  • Cloudflare 正好代表着云计算的种类之一,他们因 Go 的生产中断不能正确地对事件进行时间安排。然后,关键来了,Cloudflare 在 John Graham-Cumming 的题为“How and why the leap second affected Cloudflare DNS”的博客文章中陈述了他们的经验,分享了他们在生产中的经验和具体细节。John 和 Cloudflare 帮助我们了解跨越第二个时钟复位的准确时序非常重要,必须保持稳定。在该文章发布的两个月后,我们设计并实施了在 Go 1.9 中运行的解决方案(实际上我们并没有使用新的 API )。

猜你喜欢

转载自blog.csdn.net/smicry/article/details/77840172