当一个线程获取某个 key 的数据后,别的线程获取这个 key 的数据要等待前面的线程释放锁。
1
swulling 2019-05-22 19:49:43 +08:00 via iPhone
用一个专门的 read lock key 来解决就行,
实际使用的时候把给 lock key 加锁或者解锁以及读 key 写到事务里就可以的 |
2
mooncakejs 2019-05-22 19:52:24 +08:00
这不就是分布式锁的意义吗
|
3
menc 2019-05-22 19:55:46 +08:00
在 redis 加一个 key 用来 lock 就好。
所有线程取数据之前读 lock key,如果是 idle 值,就 write 1 次本线程 id,再 read 一次,如果 read 到的 id 是本线程,则抢到锁,去读数据,读完后将 lock key 的 value 置回 idle 即可。如果非 idle 值,就等待直到 value 变成 idel 值 先 write 1 次再 read 是考虑多个线程抢占 lock 的情况,只允许一个线程拿到锁,所以每个线程尝试一次,谁抢到算谁的。 |
4
usingnamespace 2019-05-22 20:52:36 +08:00 via iPhone
@menc 但是第一次 write 后的不就是希望把锁给第一次 write 的这个(调用 /进程 /进程 /上游)吗?真的有必要写了就让大家读一次?
|
5
raychar 2019-05-22 20:57:38 +08:00
etcd
|
6
Chanston 2019-05-22 20:59:22 +08:00
另外增加一个 key 作为 lock,获取 lock 时用 redis 的 setNx 方法(意思是 SET if Not eXist, 如果 lock 已经存在,那么就无法 set 了;不同语言的 redis client 可能方法名不一定叫这个,但应该都有对应的方法的)。
如果 setNx 成功表示加锁成功,然后就可以执行你的读取数据的操作了,执行完之后需要将 lock key 删除; 如果 setNx 失败表示已有前面的线程在使用,需要等待一定时间然后重试 setNx 搜索 redis 分布式锁,可以看到更多详细的使用介绍 |
7
menc 2019-05-22 21:12:15 +08:00
@usingnamespace 多个 write 可能覆盖
|
8
vindurriel 2019-05-22 21:22:19 +08:00 via iPhone 2
|
9
usingnamespace 2019-05-22 23:29:46 +08:00 via iPhone
@menc 然而 redis 并不是多适合分布式锁
|
10
kimown 2019-05-23 08:12:41 +08:00 via Android
|
12
ryanking8215 2019-05-23 09:44:39 +08:00
|
13
jifengg 2019-05-23 11:37:49 +08:00
楼上说的是用 redis “实现”锁的方式。
redis 本身并不支持“锁定”不让读或写。 需要通过你的业务代码去实现。也就是说,即使用了楼上说的“锁”,所有的代码也都得遵循这个机制来写才行,如果有的代码就不管你实现的锁,直接去做读写操作,那也是可以的。 |
14
rizon 2019-05-23 12:25:18 +08:00
|
15
buhi 2019-05-23 13:50:33 +08:00
@menc 的方法会有问题, 就像上面某位说的不是原子操作, 例如
[idle]线程 A 读 [idle]线程 B 读 [idle]线程 A 写 [A]线程 A 读 (A 认为自己拿到了锁) [A]线程 B 写 [B]线程 B 读 (B 认为自己拿到了锁) |
16
vindurriel 2019-05-24 12:13:25 +08:00 via iPhone
@kimown 是的 比如程序刚拿到锁就挂了
|