当前位置: 首页 > 科技观察

分布式系统问题之时钟问题

时间:2023-03-13 13:41:17 科技观察

本文转载自微信公众号《程序员先生》,作者:程序员先生。转载本文请联系程序员Sir公众号。上一篇文章介绍了网络问题。本文将进一步介绍另一个问题:时间2.时钟问题2.时钟问题时钟对于应用来说非常重要,很多指标都可以通过时钟来衡量。比如每秒的请求数,平均请求时间等,这些数据都是用时间间隔(Duration)来表示的。另一类,比如文章什么时候发表,缓存什么时候过期等等,用PointsinTime来表示。在分布式系统中,由于请求会被网络延迟,我们不知道网络延迟了多长时间,所以当涉及到多台机器时,每台机器都会记住事件发生的时间,我们可能无法确定事件的发生发生的先后顺序,因为网络延迟不确定,如果事件在时间上非常接近,可能会出现时钟问题。另外,由于每台机器都有自己的时钟,这是由硬件决定的,所以可能会有一些差异。时钟不同步的问题可以通过网络时间协议来缓解,或者可以通过GPS等服务获取精确的网络时间。2.1.MonotonicVersusTime-of-DayClocks(单调与时间时钟)现代计算机至少包含两种时钟:挂钟时间(Wall-clockTime)(与通用时钟对应的时钟),以及单调时间时钟。从本质上讲,它们都代表时间,但目的不同。挂钟(Wall-clockTime)挂钟根据日历返回当前日期和时间,这与我们日常对时钟概念的理解是一致的。例如,Java中的System.currentTimeMillis()表示自1970年1月1日以来的毫秒数。挂钟通常使用NTP进行时钟同步,但如果本地时钟比NTP服务器快得多,则可能会跳到错误的时间点.此外,挂钟会忽略闰秒,使其不适合计算时间间隔(ElapsedTime)。MonotonicClocks单调时钟更适用于计算时间间隔(Duration,TimeInterval),例如超时或服务器响应时间。例如,Java中的System.nanoTime()返回单调时钟。单调时钟保证时间数字总是变大。如果NTP检测到本地石英比时间服务器快或慢,NTP将调整本地石英的振动频率。默认情况下,NTP允许改变频率的最大范围是.但是NTP并不直接调整单调时钟的值。单调时钟非常准确,通常测量低至微秒的时间间隔。注意一个单调时钟的值是没有意义的,比较不同节点上的单调时钟的值也没有意义,因为它们可能代表不同的意义和基数。通常,单调性总是用来衡量任务的持续时间。2.2.时钟同步和精度(ClockSynchronizationandAccuracy)单调时钟不需要同步,但是挂钟需要根据NTP服务器进行调整。但是挂钟和NTP也有可能出现错位,例如由于石英钟本身的振荡漂移(Drifts)或者NTP同步时的网络延迟等。资料显示,当时间通过网络,误差至少达到35毫秒,最坏情况下误差甚至超过1秒。此外,部分用户可能会故意调整本地时钟,将其设置为错误的日期(例如,为了避免游戏的时间检查等)。因此,挂钟可能非常不准确。如果一个问题依赖于时钟同步,那么我们就需要考虑如果不同步会给应用带来什么问题。例如,一个常见的问题是:跨节点的事件排序。如果它高度依赖于时钟同步,这可能会导致问题。像下面的例子:另一个使用时钟会导致问题的例子是这样的:假设数据库每个分区只有一个主节点,并且只有主节点可以接受写入。那么其他节点如何保证当前主节点仍然是主节点呢?一种思路是主节点从其他节点获得租约。当租约没有到期时,当前节点可以处理请求,否则不能。伪代码如下:while(true){request=getIncomingRequest();//Ensurethattheleasealwaysshasatleast10secondsremainingif(lease.expiryTimeMillis-System.currentTimeMillis()<10000){lease=lease.renew();}if(lease.isValid()){process(request);}}如果当前lease还有效,离结束还有13秒,lease.isValid()消耗了15秒,所以当process(request)开始执行时,lease已经过期,其他节点可能成为主节点。这样,当前节点就不是master节点了,但是仍然执行处理写请求的操作。这会导致问题。这种情况可能是ProcessPause引起的。进程可能因多种原因而暂停,例如垃圾回收(GC)。总结分布式系统可能会遇到网络问题、时钟问题等,而且分布式系统的关键特征是局部故障。所以在分布式环境下,我们的目标是构建一个可以容忍局部故障的软件系统。为了做到这一点,我们首先必须能够检测到错误,这并不容易,所以大多数分布式算法都依赖超时来判断服务是否正常。但是超时不能区分是网络问题还是节点故障。如果由于临时网络原因被误认为是某个节点故障,这个节点就会“受委屈”,可能会导致服务不稳定。系统检测到错误后如何容忍也是一个难题。在分布式环境中,所有节点通过网络进行通信,网络本身是不可靠的。因此,单个节点不一定能做出正确的决定,需要多个节点共同投票才能做出决定。参考文献[1]Kleppmann,Martin。设计数据密集型应用程序:可靠、可扩展和可维护系统背后的重要思想。“O'ReillyMedia,Inc.”,2017年。