Trouble with Distributed Systems (3-2) - Unreliable Clocks

接续 Day 10

时钟同步和精度 (CLock Synchronization and Accuracy)

昨天讲的 单调递增时钟 (Monotonic Clock) 不需要同步,而 日历钟 (Time-of-Day Clock) 就需要与 NTP 服务器或外部时间资源做同步,但依旧很不幸的,你希望它应该是正确的时钟并不是这麽可靠,以下是可能会发生的鬼故事:

  • 电脑内的石英钟不是那麽准确,它会因为温度而漂移 (drifts),Google 假设其服务器的漂移为 200 ppm (百万分之一 - parts per million),这就代表了重新同步的时钟每 30 秒会发生 6 毫秒 (ms) 的漂移,或每一天有17 秒的漂移。
  • NTP 服务器可能意外地被防火墙档住。
  • NTP 同步的效果跟网路延迟成正相关,一个实验展示了透过网路进行同步时会有 35 毫秒 (ms) 的最小误差,在网路壅塞的场景可能会到 1 秒以上。
  • 闰秒会让一分钟只有 59 秒或 61 秒长,会让一些设计不良,没有考虑到闰秒的系统时序假设坏掉,事实上,闰秒曾让许多大型系统死亡;最佳的解决方法就是让 NTP 服务器说谎,在一天中逐步地调整
  • 在虚拟机中,硬体时钟也是虚拟的,因为 CPU 资源是与其他 VM 分享,暂时没在执行的 VM 会暂停几 10 毫秒,所以从应用系统的角度来看,时钟就会发生瞬间往前进的情况。

虽然大多数人的公司都不太在意时间问题啦!但如果你的系统是跟投资相关,就会有法规要求你的时间精度,像 MiFID II (欧洲金融市场工具指令)就要求有高频交易的金融机构,他们的时钟不得与 UTC 时间有超过 100 微秒以上的误差。

依靠同步化时钟

强壮的软件也是需要为了不准确的时钟做准备!不准确的时钟之影响是缓慢且巨大的,如果石英钟有缺陷或 NTP 使用者端未设定好,应用系统大多数的工作依旧会正常运作,时钟缓慢的漂移,慢慢的远离真实时间,直到它发生了意想不到的故障。

因此,若你的应用系统会依靠同步化时钟,必须要确保和检测所有机器节点的时间偏移量,任一节点时间漂移过多要视为节点故障并从丛集中移除。

接下来就举个依赖日历钟结果悲剧的例子吧!

顺序性事件的时间戳记 (timestamp)

这里有个 multi-lead (2020 Day 23) 分散式资料库,资料库会依靠事件的时间戳记 (timestamp) 做事情;若有 2 个用户端同时往资料库写资料,如下图 8-3, Client A 写 x = 1 到 node 1, 它复制资料到 node 2 和 3,Client B 往 node 3 对 x 累加 1(我们知道 x 应为 2)。

每个写入都依据了日历钟标注了发生时的 timestamp,在这个例子中,node 1 和 node 3 的时间偏移小於 3 毫秒 (ms),现在 node 1 x = 1 的 timestamp 为 42.004 秒,但 node 3 x 累加 1 的 timestamp 却是 42.003 秒,node 2 同时接收到这 2 笔 replica,这就代表了若是使用 最後写的是赢家 (last write wins) 策略,node 3 的写入会被丢弃。

就算你使用了 NTP 同步日历钟,这种情况还是有可能会发生(如本篇文前半部份讲的鬼故事),那这样怎麽办呢?我们可以使用一个累加的 counter 来取代日历钟解决事件的排序问题,也称为 逻辑时钟 (logical clocks),它只关心事件的相关顺序,也就是 happns-before 关系。


先这样啦 XDDDD


<<:  Day11 - Google Kubernetes Engine(GKE) 轻松架起 k8s 环境

>>:  Day11 Docker

日常要讲干话,但我不会

什麽时候会要讲干话?不满於现况,或是觉得现在面临的事情让人快承受不了。 讲干话抒发心情,大家多多少少...

Day 20 - Maybe Monad II (Piping)

Review 前一篇文章我们谈到了如何实作一个 Maybe Monad,而其主要的功能就是处理无值的...

D20/ 怎麽在 compose 与 non-compoe 间传资料 - Compose Side-Effect part 2

今天大概会聊到的范围 rememberUpdateState 上一篇聊到,SideEffect 周...

Python 多赋值问题,推论过程与结果

题目来源:邦友问答,因觉得有趣就尝试推论看看 python 多赋值是如何运作的 以下是我推论出来的,...

DAY 6:Feature Pattern,我把未来托付给你了!

什麽是 Future Pattern? 呼叫者将 task 交给 goroutine 执行,执行完毕...