大约翻译且概括一下这两篇文章
首先是
https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html提出了两个具体的问题,都和超时有关系
1. Protecting a resource with a lock 和 Making the lock safe with fencing 这两段
因为这个锁有超时的设定,所以有可能 A 拿到了锁,然后 A 卡住了,然后超时,然后 B 也拿到了锁,这样锁就崩了。
然后提供了一个解法,说 A 拿到锁之后再拿一个 token ( 33 ),B 拿到锁的时候也拿一个 token ( 34 ),这个 token 是递增的。然后 B 用 34 来 commit,然后 A 用 33 commit,这样系统可以拒绝 A 的 commit
但是他又说他不知道具体怎么实现这个解法。
2. Using time to solve consensus 和 Breaking Redlock with bad timings 这两段
因为 Redis 用 gettimeofday 来计算超时,所以如果有人(或者程序)修改了系统时间,这个超时就错了,后面当然锁也崩了。
然后是 Redis 作者的回复,
http://antirez.com/news/101 对第一个问题,提出了 2 个反驳
1. 上面的解法( Making the lock safe with fencing )不可行,因为这个解法需要能够把 A 的操作 revert 掉(依赖于 transactional memory )。如果你都已经有 transactional memory 了,那锁就不重要了。
2. 解法不可行,因为这个解法依赖 linearizable store 。也就是说如果 A 先拿 33 来 commit 然后 B 再用 34 来 commit,系统不会出现 lost updates 。但常见情况是 A 的操作会被 B 覆盖(没有 linearizable store 的情况)。
对第 2 个问题,Redis 作者说
However I think Martin is right that Redis and Redlock implementations should switch to the monotonic time API provided by most operating systems in order to make the above issues less of a problem. This was proposed several times in the past, adds a bit of complexity inside Redis, but is a good idea: I’ll implement this in the next weeks.
作者说他会改用 monotonic time,这个问题就算是解决了。
所以核心就是第一个问题,他俩互相说对方的方案不可行,其实都没有给出能让对方认可的方案。
我觉得吧,如果存在一个能解决这所有问题的算法,应该有人直接给出那个算法,“你这个算法不行” 太没有建设性了。