我对为什么分布式事务需要同步时钟的理解如下
假设 NTP 最大漂移为 250ms
true time = 100ms
node A local time = 100ms
node B local time = 0ms
以下交易将遇到顺序冲突
transactionA arrive nodeA at (true time 100ms, A time 100ms, B time 0ms)
transactionA commit by nodeA at (true time 110ms, A time 110ms, B time 10ms)
nodeB gets transactionA replicated at (true time 111ms, A time 111ms, B time 11ms) BUT with timestamp (110ms)
transactionB arrive nodeB at (true time 120ms, A time 120ms, B time 20ms)
transactionB is commit by nodeB at (true time 130ms, A time 130ms, B time 30ms)
现在transactionA和transactionB之间的交易时间有冲突
transactionA commit time = 110ms (local of A)
transactionB commit time = 30ms (local of B)
事务 A 应该在事务 B 之前处理,但是由于节点 B 落后节点 A 100ms,所以现在认为事务 B 在事务 A 之前处理
Spanner 有原子钟,保证最大时间漂移为 7ms,并且在提交之前等待 7ms 的最大不确定时间。但这如何从根本上解决问题呢?
想象下面的例子
true time = 7ms
node A local time = 7ms
node B local time = 0ms
trxA arrive nodeA at (true time 7ms, A time 7s, B time 0ms)
trxA commit by nodeA at (true time 8ms, A time 8ms, B time 1ms)
trxB arrive nodeB at (true time 9ms, A time 9ms, B time 2ms)
trxB is commit by nodeB at (true time 10ms, A time 10ms, B time 3ms)
nodeA report trxA after waiting 7ms (true time 15ms, A time 15ms, B time 8ms)
nodeB report trxB after waiting 7ms (true time 17ms, A time 17ms, B time 10ms)
在这个例子中,7ms等待并不能解决问题,trxB仍然在3ms(本地nodeB时间)提交,trxA在8ms(本地nodeA时间)提交
trxB在trxA之前提交的冲突仍然存在
我在这里缺少什么?
我在这里缺少什么?
这并不是 Spanner 时间戳分配的工作原理:您可以参考 https://static.googleusercontent.com/media/research.google.com/en//archive/spanner-osdi2012.pdf,第 4.1.2 节了解更多细节)。看来您假设事务是使用本地节点时间时间戳提交的,而实际上时间戳选择为 TrueTime.Latest。
因此,在您的示例中,不匹配位于以下几行:
trxB 到达节点B(真实时间9ms,A时间9ms,B时间2ms) trxB为 由nodeB提交(真实时间10ms,A时间10ms,B时间3ms)
在这里,您似乎认为 trxB 提交时间戳将为 3ms,这小于 trxA 提交时间戳 8ms。 然而,如果你说真实时间是 9ms(实际上,并不清楚你的意思,因为真实时间不是由一个值表示,而是由两个值表示:最早和最新),当 txnB 到达 NodeB 时,提交时间戳为B 不能是 3ms,因为 Spanner 选择提交时间戳为 TrueTime.Later,不会小于 9ms。
因此,最好根据实时和真实时间值对重写您的示例:因此,在您的示例中,节点A和节点B之间的漂移是7毫秒,节点A时间是完美的(TrueTime.Earliest=TrueTime.Latest)。
因此,如果客户端在收到 TxnA 的响应后发送 TxnB,则 TxnA 的提交时间戳将始终小于 TxnB 的提交时间戳。