Redis 有什么给 key 加锁的方法吗?

2019-05-22 19:45:47 +08:00
 deweixu

当一个线程获取某个 key 的数据后,别的线程获取这个 key 的数据要等待前面的线程释放锁。

4205 次点击
所在节点    程序员
16 条回复
swulling
2019-05-22 19:49:43 +08:00
用一个专门的 read lock key 来解决就行,

实际使用的时候把给 lock key 加锁或者解锁以及读 key 写到事务里就可以的
mooncakejs
2019-05-22 19:52:24 +08:00
这不就是分布式锁的意义吗
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 的情况,只允许一个线程拿到锁,所以每个线程尝试一次,谁抢到算谁的。
usingnamespace
2019-05-22 20:52:36 +08:00
@menc 但是第一次 write 后的不就是希望把锁给第一次 write 的这个(调用 /进程 /进程 /上游)吗?真的有必要写了就让大家读一次?
raychar
2019-05-22 20:57:38 +08:00
etcd
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 分布式锁,可以看到更多详细的使用介绍
menc
2019-05-22 21:12:15 +08:00
@usingnamespace 多个 write 可能覆盖
vindurriel
2019-05-22 21:22:19 +08:00
@menc 你的方法不是原子的
@Chanston 的方法基本正确 但没有超时 正确的实现应该是 SET key value timeout NX
usingnamespace
2019-05-22 23:29:46 +08:00
@menc 然而 redis 并不是多适合分布式锁
kimown
2019-05-23 08:12:41 +08:00
@vindurriel

加 timeout 的原因是如果 key 一直处于锁状态, client 会一直等待吗
ihipop
2019-05-23 09:10:27 +08:00
@kimown 不加 timeout 你的加锁线程挂了以后就一直锁着了
ryanking8215
2019-05-23 09:44:39 +08:00
jifengg
2019-05-23 11:37:49 +08:00
楼上说的是用 redis “实现”锁的方式。
redis 本身并不支持“锁定”不让读或写。
需要通过你的业务代码去实现。也就是说,即使用了楼上说的“锁”,所有的代码也都得遵循这个机制来写才行,如果有的代码就不管你实现的锁,直接去做读写操作,那也是可以的。
rizon
2019-05-23 12:25:18 +08:00
buhi
2019-05-23 13:50:33 +08:00
@menc 的方法会有问题, 就像上面某位说的不是原子操作, 例如
[idle]线程 A 读
[idle]线程 B 读
[idle]线程 A 写
[A]线程 A 读 (A 认为自己拿到了锁)
[A]线程 B 写
[B]线程 B 读 (B 认为自己拿到了锁)
vindurriel
2019-05-24 12:13:25 +08:00
@kimown 是的 比如程序刚拿到锁就挂了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/566690

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX