为什么Google的TrueTime API很难复制?
我不确定为什么媒体普遍认为谷歌的TrueTime API难以复制(有线,Slashdot等)。
我可以理解获得谷歌实现的低错误间隔是多么困难,但我不知道API本身将如何变得非常困难。
例如,我掀起了一个黑客攻击版本。 这是间隔。
typedef struct TT_interval { struct timeval earliest; struct timeval latest; } TT_interval;
这是现在的function。
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, 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这样的东西被建在顶部?
实现TrueTime API的挑战在于您必须提供的保证 。 也就是说,绝对时间绝不能超出系统中任何服务器上的TrueTime间隔。 如果发生这种情况,那么事件的绝对排序就会丢失,而Spanner的大部分保证都会丢失。
Spanner论文通过综合手段实现了这一目标(第3节):
- 多个时间服务器,具有不同的源(GPS,primefaces钟),包括来自其他数据中心的时间服务器。
- Marzullo的算法用于检测骗子并将各种可信时间源复用到本地机器时钟的更新中。
- 在时钟同步之间应用的假设时钟频率漂移为200us / s。
- 从系统中踢出机器,其表现出测量的本地时钟漂移>阈值(阈值<< 200us / s,必要时)。
现在,您可以通过更简单的方法实现这一点 – NTP和假设的错误间隔为10分钟就可以了。 但正如问题所述,这对性能有影响。 读写事务(4.2.1)必须等待提交,预期等待时间为2 * errorAverage – 在此示例中为20分钟。 同样,“现在”时间的只读交易(4.2.2) – 而不是过去的时间 – 必须等待安全时间足够进展; 在这个例子中至少10分钟。 因此,要拥有一个高性能系统,您需要尽可能地最小化错误间隔, 而不会丢失您的保证,这是复杂性产生的地方。
我不确定你的系统中是如何调用ntp_adjtime的 – 它可能已经使用多个不受信任和不相关的时间源进行设置,在这种情况下,你已经完成了大部分时间。 如果您还可以确保maxerror值保证比系统可能的时钟漂移更快,那么您应该很高兴。 Spanner的大多数表现,没有你自己的个人primefaces钟:)。