19

我正在考虑在我的应用程序中编写一个简单的同步功能,其中一个出现的问题是两台远程计算机之间的时间同步,每台计算机都有自己的时钟(特别是关于文件/对象的修改日期)。

我确信已经对这个主题进行了很多研究并且不想过于理论化,但我想知道是否有任何公认的最佳实践来最小化远程时钟之间的时间差异?

例如,一开始是始终使用通用时间 (UTC) 以避免时区问题,但不能保证两台计算机将具有完全相同的系统时间。幸运的是,我正在做的工作不是很细粒度,所以这不是一个非常重要的问题,但我仍然很好奇。

一种解决方案是始终在两端使用相同的时钟,例如全局时间服务器,而不是本地系统时钟。大概这(结合共享资源锁)可以保证同步时间不会意外重叠,但它不是很实用。

一个想法突然出现在我的脑海中,将每个节点(每个客户端)与之前某个时间点计算的偏移量同步,也许是通过计算系统时钟与全局时间服务器的偏移量。这只需要偶尔进行,因为偏移量本身不太可能在短时间内发生很大变化。

更新:让我补充一点,我对实际同步两台计算机的系统时钟不感兴趣——我假设操作系统在大多数情况下都会处理这个问题。这只是一个关于如何确保应用程序的两个实例使用同步时间的问题,尽管在这个时代,我认为系统时钟几乎肯定会在一些非常小的增量内同步。

4

9 回答 9

20

正如其他人所推荐的那样,在您的应用程序中依赖 NTP 是一件容易的事。正确的做法是使用 Lamport 的分布式时钟同步算法。在他 1978 年的经典论文《时间、时钟和分布式系统中事件的顺序》中对此进行了解释。

于 2008-12-23T17:25:25.123 回答
8

查看“网络时间协议”(NTP)规范。

于 2008-12-23T16:57:52.683 回答
6

You can try PTP, The Precision Time Protocol (PTP) is a protocol used to synchronize clocks throughout a computer network. On a local area network it achieves clock accuracy in the sub-microsecond range, making it suitable for measurement and control systems. http://en.wikipedia.org/wiki/Precision_Time_Protocol

于 2013-03-07T17:26:09.217 回答
3

将它们与NTP网络时间协议同步。

你在哪个平台?

使用 NTP,您可以将计算机时间与原子钟同步,并使用世界官方时间。

于 2008-12-23T16:57:45.553 回答
3

与其编写代码来同步时钟,难道不能在两台机器上都运行一个 ntp 客户端吗?

或者,如果上述方法不可行并且您的应用程序以足够的权限运行来设置时间,我会很想在应用程序中实现最小的 NTP 客户端权限并尝试将其与公共服务器同步。只是不要硬编码某人的私人服务器......

于 2008-12-23T16:58:37.453 回答
3

对于不成熟的最终用户,这是我目前必须解决的一个问题,他们可以做很多事情来破坏先前贡献者提出的明智建议。一个不成熟的最终用户至少可以做这些事情,甚至更多:

1)没有足够的计算知识能够设置ntp时间同步

2)将他们的计算机时钟设置为不正确的家庭时钟或手机时钟

3) 在 Windows XP 中不小心禁用了 ntp 时间同步并且不知道如何再次启用它,或者他们的计算机日期设置错误,在这种情况下 Windows ntp 不起作用

4) 电脑 BIOS 电池没电了,所以电脑总是在 1970 年启动!

5) 用户将笔记本电脑带到国外,暂时将笔记本电脑时钟设置为当地时间,但不更改时区,所以现在电脑会返回错误的UTC时间!!!

所以你的程序本身必须管理时间,当然你希望以最小的开销来做到这一点。

让我们假设运行您的程序的两个最终用户需要这些程序在将来的同一绝对时间做某事。

我提出了这个方案,它从 cron 工作的工作方式中汲取了一些想法,如果有人能提出改进这个想法的建议,我会很高兴。

1)当您的应用程序启动时,它通过对第三方服务器或您自己的时间服务器的soap调用将自己的内部UTC时间同步到ntp(您可以自己使用ntp保持时间)。

2) 之后,它会从系统时钟添加经过时间以保持时间。如果要求很严格,您可能需要每隔一段时间重复一次 ntp 同步。

3) 然后应用程序查看它需要按时完成的未来工作列表。它需要知道最早的工作。

4)然后它创建一个线程,它在最早的工作之前将其休眠一段时间,减去安全裕度,这取决于您的要求可能提前 10 分钟,提前一小时或两个小时等。

5) 当线程唤醒时,它会通过进一步的soap调用重新检查绝对时间,然后依靠系统时钟来增加经过的时间,直到它到达第一个作业应该执行的时间。

6) 一旦作业被触发(在另一个线程中运行),时间监控线程就会提前计算下一个任务时间,并在此期间再次进入睡眠状态。

想法的增强:

1) 用户可能会在作业到期之前关闭你的应用程序,因此你可能需要一个后台进程或服务,它使用与上述相同的同步方案,来独立监控你的作业列表,存储在数据库或文件中,并启动及时申请。(在 Windows 中,产生应用程序进程)

2) 您的应用程序可能正在动态添加较新、较早的作业或删除作业,因此您的睡眠线程可能需要可唤醒才能重新计算新的较早作业或已删除作业之后的作业。在 Win32 中,您可以通过您的线程在某个事件上等待超时来执行此操作,您将其设置为强制它重新计算睡眠时间。在 Linux 中无疑也有类似的机制。

3) 对于获取时间的 Soap 调用,请记下 Soap 的发送时间和响应的接收时间。如果周转时间太长,您不能依赖时间,可能需要重复通话,或者您可以妥协。例如,如果 Soap 说计算机时钟快 5 分钟,但 Soap 呼叫本身需要一分钟才能回复,那么您只能肯定地说计算机时钟至少快 4 分钟。

于 2009-10-31T13:34:27.073 回答
2

我们做的一件事本质上是将所有定时操作卸载到“主机”机器上。例如,如果您有 20 台服务器都共享一个 DB,则使用 DB 的时间。如果您有一个中央服务器和一百万台客户端机器,那么客户端机器不应该负责计时任何事情;做你所有的同步服务器端。在真正的“分布式”环境中,例如 P2P 网络或其他东西,使用最直接“拥有”相关资源的机器(您要写入的文件的实际 PC)来同步/控制对文件的访问。

于 2008-12-23T17:18:37.663 回答
0

任何联网的机器都应该使用 NTP。所有现代系统都包含一种简单的设置方法。如果您需要一点额外的精度,唯一的问题应该是选择特定的服务器;但它已经在毫秒范围内,所以我不在乎,通常只是指向 pool.ntp.org

于 2008-12-23T17:04:17.803 回答
0

Don't use NTP. NTP is for getting date/time only.

It works to synchronize events between apps that don't communicate. An alarm app and your body, for instance.

For apps that have direct communication, sharing a resource, use lamport clocks or vector clocks as Diomidis said. Lamport clocks work great to achieve a partial order between events, Vector clocks are great when you need to identify concurrent events.

于 2011-07-15T20:19:38.317 回答