首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  程序员

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

  •  
  •   deweixu · 200 天前 · 2188 次点击
    这是一个创建于 200 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    16 回复  |  直到 2019-05-24 12:13:25 +08:00
        1
    swulling   200 天前 via iPhone
    用一个专门的 read lock key 来解决就行,

    实际使用的时候把给 lock key 加锁或者解锁以及读 key 写到事务里就可以的
        2
    mooncakejs   200 天前
    这不就是分布式锁的意义吗
        3
    menc   200 天前
    在 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   200 天前 via iPhone
    @menc 但是第一次 write 后的不就是希望把锁给第一次 write 的这个(调用 /进程 /进程 /上游)吗?真的有必要写了就让大家读一次?
        5
    raychar   200 天前
    etcd
        6
    Chanston   200 天前
    另外增加一个 key 作为 lock,获取 lock 时用 redis 的 setNx 方法(意思是 SET if Not eXist, 如果 lock 已经存在,那么就无法 set 了;不同语言的 redis client 可能方法名不一定叫这个,但应该都有对应的方法的)。
    如果 setNx 成功表示加锁成功,然后就可以执行你的读取数据的操作了,执行完之后需要将 lock key 删除;
    如果 setNx 失败表示已有前面的线程在使用,需要等待一定时间然后重试 setNx

    搜索 redis 分布式锁,可以看到更多详细的使用介绍
        7
    menc   200 天前
    @usingnamespace 多个 write 可能覆盖
        8
    vindurriel   200 天前 via iPhone   ♥ 2
    @menc 你的方法不是原子的
    @Chanston 的方法基本正确 但没有超时 正确的实现应该是 SET key value timeout NX
        9
    usingnamespace   200 天前 via iPhone
    @menc 然而 redis 并不是多适合分布式锁
        10
    kimown   199 天前 via Android
    @vindurriel

    加 timeout 的原因是如果 key 一直处于锁状态, client 会一直等待吗
        11
    ihipop   199 天前 via Android
    @kimown 不加 timeout 你的加锁线程挂了以后就一直锁着了
        13
    jifengg   199 天前
    楼上说的是用 redis “实现”锁的方式。
    redis 本身并不支持“锁定”不让读或写。
    需要通过你的业务代码去实现。也就是说,即使用了楼上说的“锁”,所有的代码也都得遵循这个机制来写才行,如果有的代码就不管你实现的锁,直接去做读写操作,那也是可以的。
        15
    buhi   199 天前
    @menc 的方法会有问题, 就像上面某位说的不是原子操作, 例如
    [idle]线程 A 读
    [idle]线程 B 读
    [idle]线程 A 写
    [A]线程 A 读 (A 认为自己拿到了锁)
    [A]线程 B 写
    [B]线程 B 读 (B 认为自己拿到了锁)
        16
    vindurriel   198 天前 via iPhone
    @kimown 是的 比如程序刚拿到锁就挂了
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1265 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 20ms · UTC 23:51 · PVG 07:51 · LAX 15:51 · JFK 18:51
    ♥ Do have faith in what you're doing.