我不确定为什么媒体会说谷歌的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这样的东西被建在顶层?
答案 0 :(得分:46)
实施TrueTime API的挑战在于您必须提供的保证。也就是说,绝对时间必须从不超出系统中任何服务器上的TrueTime间隔。如果发生这种情况,那么事件的绝对排序就会丢失,就像Spanner的大部分保证一样。
Spanner paper通过手段的组合实现了这一点(第3节):
现在,你可以以更简单的方式实现这一点 - NTP和10分钟的假定错误间隔可以做到。但正如问题所述,这对性能有影响。读写事务(4.2.1)必须等待提交,预期等待时间为2 * errorAverage - 在此示例中为20分钟。同样,在“现在”时间的只读交易(4.2.2) - 而不是过去的时间 - 必须等待安全时间进展得足够远;在这个例子中至少10分钟。因此,要拥有一个高性能系统,您需要尽可能地最小化错误间隔,没有失去保证,这就是复杂性出现的地方。
我不确定你的系统中是如何调用ntp_adjtime的 - 它可能已经使用多个不受信任和不相关的时间源进行设置,在这种情况下你已经完成了大部分时间。如果您还可以确保maxerror值保证比系统可能的时钟漂移更快,那么您应该很高兴。 Spanner的大多数表现,没有你自己的个人原子钟:)。