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

Jon*_*rst 30 c time distributed-computing google-cloud-platform google-cloud-spanner

我不确定为什么媒体普遍表示谷歌的TrueTime API难以复制(有线,Slashdot等).

我可以理解如何获得谷歌实现的低错误间隔是一件困难的事情,但我不知道API本身将如何变得非常困难.

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

    typedef struct TT_interval {
            struct timeval earliest;
            struct timeval latest;
    } TT_interval;
Run Code Online (Sandbox Code Playgroud)

这是现在的功能.

    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;
    }
Run Code Online (Sandbox Code Playgroud)

最后,这里是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;
    }
Run Code Online (Sandbox Code Playgroud)

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

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

Eri*_*ett 48

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

所述扳手纸通过的装置(第3节)的组合实现这样的:

  1. 多个时间服务器,具有不同的源(GPS,原子钟),包括来自其他数据中心的时间服务器.
  2. Marzullo的算法用于检测骗子并将各种可信时间源复用到本地机器时钟的更新中.
  3. 在时钟同步之间应用的假设时钟频率漂移为200us/s.
  4. 从系统中踢出机器,其表现出测量的本地时钟漂移>阈值(阈值<< 200us/s,必要时).

现在,您可以通过更简单的方法实现这一点 - NTP和10分钟的假定错误间隔可以完成.但正如问题所述,这对性能有影响.读写事务(4.2.1)必须等待提交,预期等待时间为2*errorAverage - 在此示例中为20分钟.同样,在"现在"时间的只读交易(4.2.2) - 而不是过去的时间 - 必须等待安全时间进展得足够远; 在这个例子中至少10分钟.因此,要拥有一个高性能系统,您需要尽可能地减少错误间隔,而不会丢失您的保证,这就是复杂性产生的地方.

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

  • 我们刚刚发布了一个关于TrueTime的新文档及其使用方法 - https://cloud.google.com/spanner/docs/true-time-external-consistency (3认同)