我不确定方法的正确设计。
我们使用放置在每个实体上的递增版本来使用乐观锁定。long
这种实体的每次更新都是通过比较和交换算法执行的,该算法成功或失败取决于其他客户端是否同时更新实体。经典的乐观锁定,例如hibernate。
我们还需要采取重试的方式。我们使用http
基于存储(etcd),并且可能会发生某些更新请求刚刚超时。
这就是问题所在。如何结合乐观锁和重试。这是我面临的具体问题。
假设我有一个实体,version=1
我正在尝试更新它。下个版本显然是2
. 我的客户比执行条件更新。只有当持久化中的版本是1
并且它被原子地更新为version=2
. 到目前为止,一切都很好。
现在,假设更新请求的响应没有到达。目前还不能说成功与否。我现在唯一能做的就是重试更新。在内存实体中仍然包含version=1
打算将值更新为2
.
现在真正的问题出现了。如果第二次更新因为持久化版本 is2
而不是而失败1
怎么办?
有两个可能的原因:
- 第一个请求确实导致了更新 - 操作成功但响应丢失或我的客户端超时,无论如何。它只是没有到达,但它通过了
- 其他一些客户端在后台同时执行更新
现在我不能说什么是真的。我的客户更新了实体还是其他客户做了?操作是通过还是失败?
我们当前使用的方法只是比较持久实体和主内存中的实体。作为 java 相等或 json 内容相等。如果它们相等,则更新方法被声明为成功。我对算法不满意,因为它对我来说既不便宜也不合理。
另一种可能的方法是不使用long
版本,timestamp
而是使用。每个客户端都会在更新操作中生成自己的时间戳,这意味着潜在的并发客户端很可能会生成其他客户端。我的问题是概率,特别是当两个并发更新来自同一台机器时。
还有其他解决方案吗?