分布式系统的麻烦
在分布式系统中,尽管系统的其他部分工作正常,但系统的某些部分可能会以某种不可预知的方式被破坏,这种没有确定性的部分失效,使得分布式系统难以工作。
1、不可靠的网络
互联网和数据中心中的大多数内部网络都是 异步分组网络(asynchronous packet networks)。在这种网络中,一个节点可以向另一个节点发送一个消息(一个数据包),但是网络不能保证它什么时候到达,或者是否到达。如果发送请求并期待响应,则很多事情可能会出错。
2、不可靠的时钟
网络上的每台机器都有自己的时钟,这是一个实际的硬件设备:通常是石英晶体振荡器。这些设备不是完全准确的,所以每台机器都有自己的时间概念,可能比其他机器稍快或更慢(为此,通过例如网络时间协议等来调整时钟)。
2.1 单调钟和日历钟
日历钟:根据某个日历(也称为 挂钟时间,即 wall-clock time)返回当前日期和时间,通常与 NTP 同步,如果本地时钟在 NTP 服务器之前太远,则它可能会被强制重置,看上去好像跳回了先前的时间点。
Linux 上的
clock_gettime(CLOCK_REALTIME)和 Java 中的System.currentTimeMillis()返回自 epoch(UTC 时间 1970 年 1 月 1 日午夜)以来的秒数(或毫秒),根据公历(Gregorian)日历,不包括闰秒。单调钟: 单调钟适用于测量持续时间(时间间隔),例如超时或服务的响应时间,他的值总是向前的,因此可以用来计算经过时间。
Linux 上的
clock_gettime(CLOCK_MONOTONIC),和 Java 中的System.nanoTime()都是单调时钟。
2.2 时钟同步及准确性1
日历钟获取同步时钟的方法并不像你所希望的那样可靠或准确 —— 硬件时钟和 NTP 可能会变幻莫测。
计算机中的石英钟不够精确,会存在运行速度快于或慢于预期的现象(也称为漂移,取决于机器的温度)。
NTP 同步只能和网络延迟一样好,所以当你在拥有可变数据包延迟的拥塞网络上时,NTP 同步的准确性会受到限制。
3、依赖同步时钟
如果使用需要同步时钟的软件,必须仔细监控所有机器之间的时钟偏移。时钟偏离其他时钟太远的节点应当被宣告死亡,并从集群中移除。这样的监控可以确保在损失发生之前注意到破损的时钟。
3.1 有序的时间戳

假设一个集群有三个节点,有两个用户分别向节点一和节点三写入数据,同时向节点二进行数据同步,如果使用时间戳进行排序并使用最后写入胜利的策略,后写入的值会像上述图所示一样被覆盖掉(通过保留最近的值来解决写入冲突)。
为此,需要一个基于递增计数器而不是振荡石英晶体的逻辑时钟来保证顺序事件的安全性,其不测量一天中的时间或经过的秒数,而仅测量事件的相对顺序。
3.2 时钟读数的置信区间
将时钟读数视为一个时间点是没有意义的 —— 它更像是一段时间范围:例如,一个系统可能以 95% 的置信度认为当前时间处于本分钟内的第 10.3 秒和 10.5 秒之间,它可能没法比这更精确了,这意味着时间戳中的微秒数字部分基本上是没有意义的。
- 感谢你赐予我前进的力量