为什么Google的TrueTime API很难复制?

时间:2013-08-22 15:32:44

标签: c time google-cloud-platform distributed-computing google-cloud-spanner

我不确定为什么媒体会说谷歌的TrueTime API难以复制(有线,Slashdot等)。

我可以理解获得Google实现的低错误间隔是多么困难,但我不知道API本身会如何变得非常困难。

例如,我掀起了一个黑客攻击版本。这是间隔。

    typedef struct TT_interval {
            struct timeval earliest;
            struct timeval latest;
    } TT_interval;

这是现在的功能。

    int TT_now(TT_interval* interval)
    {
        struct ntptimeval tv;
        struct timeval delta;

        struct timeval* earliest_p = &(interval->earliest);
        struct timeval* latest_p = &(interval->latest);
        struct timeval* now_p = &(tv.time);
        struct timeval* delta_p = δ

        timerclear(&delta);
        timerclear(&interval->earliest);
        timerclear(&interval->latest);

        if(ntp_gettime(&tv) == 0) {
            tv.maxerror = tv.maxerror > 0 ? tv.maxerror : -(tv.maxerror);

            delta.tv_sec = delta.tv_sec + (tv.maxerror / 1000);
            delta.tv_usec = delta.tv_usec + ((tv.maxerror % 1000) * 1000);

            if(delta.tv_usec > 1000000) {
                delta.tv_usec -= 1000000;
                delta.tv_sec++;
            }

            timeradd(now_p, delta_p, latest_p);
            timersub(now_p, delta_p, earliest_p);
        } else {
            printf("error on ntp_gettime. %s\n", strerror(errno));
            return ERROR;
        }

        return SUCCESS;
    }

最后,这里是before和after函数(它们是now函数的包装器,可以使用一些DRY重构)。

    int TT_before(TT_interval* interval, bool* success)
    {
        struct timeval* latest_p;
        struct timeval* earliest_p;
        TT_interval now;

        if(TT_now(&now) != SUCCESS) {
            return ERROR;
        }

        latest_p = &(interval->latest);
        earliest_p = &(now.earliest);

        if(timercmp(latest_p, earliest_p, <) != 0) {
            *success = true;
            return SUCCESS;
        } else {
            *success = false;
            return SUCCESS;
        }

        return ERROR;
    }

   int TT_after(TT_interval* interval, bool* success)
    {
        struct timeval* latest_p;
        struct timeval* earliest_p;
        TT_interval now;

        if(TT_now(&now) != SUCCESS) {
            return ERROR;
        }

        earliest_p = &(interval->latest);
        latest_p = &(now.earliest);

        if(timercmp(latest_p, earliest_p, <) != 0) {
            *success = true;
            return SUCCESS;
        } else {
            *success = false;
            return SUCCESS;
        }

        return ERROR;
    }

我似乎得到大约5,000us到350,000us的间隔错误(使用公共NTPd)。这与谷歌的数字相差甚远,但你需要从某个地方开始。

除了表现不佳之外,这个设计中是否存在一个严重缺陷,会阻止像Spanner这样的东西被建在顶层?

1 个答案:

答案 0 :(得分:46)

实施TrueTime API的挑战在于您必须提供的保证。也就是说,绝对时间必须从不超出系统中任何服务器上的TrueTime间隔。如果发生这种情况,那么事件的绝对排序就会丢失,就像Spanner的大部分保证一样。

Spanner paper通过手段的组合实现了这一点(第3节):

  1. 多个时间服务器,具有不同的来源(GPS,原子钟),包括来自其他数据中心的时间服务器。
  2. Marzullo的算法用于检测骗子并将各种可信时间源复用到本地机器时钟的更新中。
  3. 假设在时钟同步之间应用的span服务器时钟漂移为200us / s。
  4. 从系统中踢出表现出测量的本地时钟漂移的机器&gt;阈值(阈值&lt; <200us / s必要时)。
  5. 现在,你可以以更简单的方式实现这一点 - NTP和10分钟的假定错误间隔可以做到。但正如问题所述,这对性能有影响。读写事务(4.2.1)必须等待提交,预期等待时间为2 * errorAverage - 在此示例中为20分钟。同样,在“现在”时间的只读交易(4.2.2) - 而不是过去的时间 - 必须等待安全时间进展得足够远;在这个例子中至少10分钟。因此,要拥有一个高性能系统,您需要尽可能地最小化错误间隔,没有失去保证,这就是复杂性出现的地方。

    我不确定你的系统中是如何调用ntp_adjtime的 - 它可能已经使用多个不受信任和不相关的时间源进行设置,在这种情况下你已经完成了大部分时间。如果您还可以确保maxerror值保证比系统可能的时钟漂移更快,那么您应该很高兴。 Spanner的大多数表现,没有你自己的个人原子钟:)。