在cockroachdb中,为什么不确定性重新启动不会更新不确定性窗口的上限?

麦可

我最近从cockroachdb博客上阅读了这篇很棒的文章,该文章讨论了它们如何以类似于扳手的方式保持一致性,但没有原子钟。这是帖子的相关部分:

当CockroachDB开始事务时,它将基于当前节点的挂墙时间选择一个临时提交时间戳。通过添加群集的最大时钟偏移量[commit timestamp,commit timestamp +最大时钟偏移量],它还会在选定的墙上时间上建立上限。该时间间隔表示不确定性的窗口。

...

仅当观察到某个值在不确定范围内时,特定于CockroachDB的机制才会起作用。此处的中心问题是,鉴于时钟偏移,我们无法确定所遇到的值是否在事务开始之前就已提交。在这种情况下,我们只需执行不确定性重新启动,以使临时提交时间戳刚好超过遇到的时间戳,就可以做到这一点。至关重要的是,不确定性区间的上限在重新启动时不会改变,因此不确定性的窗口会缩小。从多个节点读取不断更新的数据的事务可能被强制重新启动多次,尽管永远不会超过不确定性间隔,或者每个节点不会超过一次。

具体来说,我不明白为什么不确定性窗口在重新启动不确定性时也不必碰到上限。这是一个例子来说明我的困惑:

假设我们有两个写操作A和B(在不同的节点上)。写入A的时间戳为3,B的时间戳为5。假设最大时钟偏移为3个时间单位,如果在当前时钟为1的节点上开始事务,则将构造不确定性窗口[1,4]。当我们遇到写操作A时,我们将执行不确定性重新启动以包括它,并将不确定性窗口减小到(3,4]。当我们遇到写操作B时,我们将忽略它,因为它位于不确定性窗口的上限之上。但是,由于我们的最大时钟偏移量是3个单位,并且A和B的时间戳相差少于3个单位,所以B可能早于A。但是我们在交易中包括了A而不是B,因此我们没有一致性。

在此先感谢您指出我所缺少的!

本·达内尔

好问题。这非常微妙。我将尝试解释发生了什么。

首先让我们看一下所涉及的交易。我们有两个写事务,A(ts = 3)和B(ts = 5)。如果这两个事务触及的键中有任何重叠,则它们将不能“无序”提交,并且我们可以确定事务A在事务B之前发生。但是,如果没有重叠的键,则存在除了时钟之外,没有任何协调点可以保证此顺序,并且由于时间戳足够接近,因此哪个“先发生”是不明确的。

在存在这种歧义的情况下,我们想做的就是分配某种顺序,以使事务按照其时间戳所隐含的顺序发生。只要我们知道没有人观察到B处于写入状态而A处于非写入状态,这是安全的。这由CockroachDB内部控制读/写交互的机制(主要是名称不佳的TimestampCache强制执行如果在时间戳6的事务B之后是事务C,该事务C读取密钥A和B,则将不再允许事务A在时间戳3进行提交(将事务A推送到时间戳7)。

只要数据库可以看到读取和写入之间的关系,此方法就起作用。有时在某些情况下我们看不到这一点,如果写入B对A具有某些带外因果关系,但从未发生过涉及这两个键的事务。这是我们称为“因果逆向”的异常,它是CockroachDB的可序列化隔离度与Spanner的线性化(或严格序列化)隔离度之间的区别。

更新不确定性区间的上限是避免因果反向异常的一种方法,尽管这样做会带来严重的实际缺陷-您可能不得不不断地重新启动,直到发现两次写入之间的间隔至少达到最大时钟偏移为止交易涉及的所有键上。这可能永远不会成功。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章