首先,我知道在 Cassandra 上不能混合使用 LWT 和非 LWT 操作是有限制的。
根据我在我们的申请中的观察,这种限制的原因之一是:
从 java driver 3.0 开始,正常插入会使用客户端生成的时间戳,而 LWT 插入会使用服务器端的时间戳,而 Cassandra 使用的是 last-write-win 策略。
我知道使用 LWT(4 往返 / paxos / 等)对性能的影响,但我们的案例是我们将 DC 级分布式锁放在 Cassandra 上。所以在尝试获取锁的时候,我们使用了LWT插入,但是为了加快锁的性能,我们在释放锁的时候使用了普通的删除。然后我们面临混合使用 LWT 和非 LWT 操作导致的数据损坏。也就是说,我们的删除成功了,但是时间戳更早,所以它没有生效。
然后我们的第一个修复是使用 writetime() 函数运行 LOCAL_QUORUM 查询来检索写入时间戳,添加 1 毫秒,并在删除时使用“USING TIMESTAMP”设置它。然后我们意识到它仍然不起作用,因为使用 LOCAL_QUORUM 检索到的时间戳似乎不是 LWT 插入的数据的最终写入时间。尽管如此,我们还是使用更早的时间戳处理删除。
所以实际上我有3个问题:
LWT 插入的数据是否在不同副本中具有不同的时间戳,这些时间戳实际上是在 LWT paxos 的第 3 步(提议/接受)期间从 Cassandra 节点生成的?
对 LWT 插入的数据执行具有一致性级别 LOCAL_QUORUM 的查询是否将响应写入时间视为其 ACK 中的最新写入时间?例如,LWT 插入的 3 个副本有 3 个不同的时间戳,LOCAL_QUORUM 查询检索其中 2 个,并使用这 2 个的最新时间戳作为响应的写入时间?
如果我们必须坚持这样做(通过 LWT 插入然后正常删除),我们是否可以使用 LOCAL_SERIAL 一致性级别和 writetime() 函数来检索时间戳,并将其用作正常删除的时间戳以确保删除有效?
或者,我们唯一的选择是对我们的用户锁使用 LWT 插入和 LWT 删除,还是放弃我们在 Cassandra 上的分布式锁?
欢迎大家讨论,提前致谢~