硬核的分布式概念,有关时间时钟问题和算法的问题


硬核的分布式概念,有关时间时钟问题和算法的问题


文章图片


硬核的分布式概念,有关时间时钟问题和算法的问题


文章图片



分布式系统中时间是核心概念 , 依靠时间多个机器才能协同交互 。 分布式数据库 微服务交互都逃不过这个硬核 。 本文概括了物理时钟和逻辑时钟等概念 。
作为软件工程师 , 我们都依赖于时间概念:确保我们程序中的事件遵循时间顺序的关键概念 。
然而 , 调用“获取当前时间”的简单调用可能会产生意外结果 , 如果使用不当会导致无法预料的后果 。
此外 , 我们在本地开发机器上观察到的关于时间的不变性可能并不一定存在于云中或任何分布式系统中 。 先上结论:

  • 使用System.nanoTime()用于测量时间间隔
  • 使用System.currentTimeMillis()获得的挂钟时间
  • 使用Clock.systemUTC().instant()用于获取挂钟时间与NS 精度
  • 即使它的精度很高 , 也不是每个时钟都能为您提供所需的分辨率
  • 挂钟时间可以关闭几十毫秒(或更多 , 或更少)
  • 如果时间同步很重要 , 请使用云提供商提供的NTP
  • 逻辑时钟可能比实际时钟更合适 , 但它们具有相关的成本

时间属性:
1. 单调性
单调递增函数意味着对于这种函数的每次后续调用 , 所产生的值永远不会小于任何先前值 。 因此 , 单调时钟是永不倒退的时钟 。 可悲的是 , 令人惊讶的是 , 这个属性不是许多时钟的特征 。
2. 分辨率Resolution
分辨率是第二个属性 。 它是两个时钟周期之间最小的可观察差异 。 带有秒针的简单机械表的分辨率为1秒 。 当你盯着手表时 , 手表位置可以是12秒或13秒 , 但不会是12点半秒 。
3.延迟Latency
当我们谈论时钟时 , 通常会忽略延迟 , 但是当我们考虑其他属性(如分辨率)时 , 它非常重要 。 例如 , 如果你手上有最精确的原子手表 , 皮秒picosecond分辨率也没关系 - 如果我问你现在是什么时间 , 你需要大约一秒 , 有时更少 , 有时甚至更多 , 看看回应 , 所有这些精度都消失了 。
那么 , Java时钟有哪些属性 , 它们如何应用于我们在开始时看到的问题?

挂钟
让我们从System.currentTimeMillis()开始吧 , 通常 , 开始探索的最佳位置是用Javadoc编写的文档 , 并且有很多内容可供参考 。 下面是对我们现在最重要的内容的摘录 。
/**
 * Returns the current time in milliseconds. Note that
 * while the unit of time of the return value is a millisecond
 * the granularity of the value depends on the underlying
 * operating system and may be larger.  For example many
 * operating systems measure time in units of tens of
 * milliseconds.
 *
 * ...
 *
 * @return  the difference measured in milliseconds between
 *          the current time and midnight January 1 1970 UTC.
 */public static native long currentTimeMillis();


我们可以看到 , 时钟为我们提供了毫秒级的精度值 , 但实际的分辨率取决于操作系统 。 此外 , 如果我们通过测量执行时间来测量延迟 , 它将会低于1毫秒 。
但java的时钟是可以倒退吗?Javadoc没有提到任何关于单调性的东西 , 所以我们需要深入挖掘 , 并看一下实现 。
本文仅探讨Linux和MacOS的本机实现 。 但是 , 类似的技术也可以应用于其他操作系统 。
该方法是原生的 , 因此实现取决于底层操作系统 。 Linux和MacOS的本机实现看起来几乎完全相同 。
Linux:
jlong os::javaTimeMillis() {
  timeval time;
  int status = gettimeofday(&time NULL);  assert(status != -1 \"linux error\");  return jlong(time.tv_sec) * 1000  +  jlong(time.tv_usec / 1000);


苹果系统:
jlong os::javaTimeMillis() {

推荐阅读