为啥 Google 的 TrueTime API 难以复制?

Posted

技术标签:

【中文标题】为啥 Google 的 TrueTime API 难以复制?【英文标题】:Why is Google's TrueTime API hard to duplicate?为什么 Google 的 TrueTime API 难以复制? 【发布时间】:2013-08-25 10:41:51 【问题描述】:

我不确定为什么媒体普遍说 Google 的 TrueTime API 难以复制(Wired、Slashdot 等)。

我可以理解要获得 Google 正在实现的低错误间隔是一件多么困难的事情,但我不认为 API 本身会有多么困难。

例如,我制作了一个 hacked together 版本。这是间隔。

    typedef struct TT_interval 
            struct timeval earliest;
            struct timeval latest;
     TT_interval;

这是 now 函数。

    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)。这与 Google 的数字相差甚远,但您需要从某个地方开始。

除了性能不佳之外,这种设计是否存在重大缺陷会阻止像 Spanner 这样的东西在上面构建?

【问题讨论】:

【参考方案1】:

实施 TrueTime API 的挑战在于您必须提供的保证。即,绝对时间必须从不在系统中任何服务器上的 TrueTime 间隔之外。如果发生这种情况,那么事件的绝对顺序就会丢失,Spanner 的大多数保证也是如此。

Spanner paper 通过多种方式实现了这一点(第 3 节):

    具有不同来源(GPS、原子钟)的多个时间服务器,包括来自其他数据中心的时间服务器。 Marzullo 的算法用于检测骗子并将各种可信时间源多路复用到本地机器时钟的更新中。 假定跨度服务器的时钟漂移为 200us/s,应用于时钟同步之间。 从系统中踢出显示测得的本地时钟漂移 > 阈值(必要时阈值

现在,您可以用更简单的方法实现这一点 - NTP 和假设的 10 分钟错误间隔将很容易做到。但正如问题中所述,这对性能有影响。读写事务 (4.2.1) 必须等待提交,预期等待时间为 2*errorAverage - 在此示例中为 20 分钟。类似地,“现在”时间的只读事务(4.2.2) - 而不是过去的时间 - 必须等待安全时间提前足够长;在本例中至少 10 分钟。因此,要拥有一个高性能的系统,您需要尽可能减少错误间隔,同时又不会失去您的保证,这就是复杂性出现的地方。

我不确定 ntp_adjtime 在您的系统中是如何被调用的 - 可能已经使用多个不受信任且不相关的时间源进行了设置,在这种情况下,您已经大部分时间在那里了。如果您还可以确保保证 maxerror 值的推进速度快于系统可能的时钟漂移,那么您应该很高兴。 Spanner 的大部分性能,无需您自己的个人原子钟 :)。

【讨论】:

我们刚刚发布了一个关于 TrueTime 的新文档以及它是如何使用的 - cloud.google.com/spanner/docs/true-time-external-consistency

以上是关于为啥 Google 的 TrueTime API 难以复制?的主要内容,如果未能解决你的问题,请参考以下文章

TrueTime的安装运行例程

在android中添加truetime库时出现错误

为啥 Google Meet 报告审核日志 API 不同步?

为啥 Youtube/Google API 不返回超过 5 个回复?

为啥“Google Maps”一书中的 Google Maps Directions API 示例对我不起作用?

Google Location API vs. Maps:为啥相同的查询会产生不同的结果?