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

人生第一篇技术文章, redis 实现分布式阻塞非争抢锁

  •  3
     
  •   kkk212 · 2020-03-14 19:44:05 +08:00 · 3572 次点击
    这是一个创建于 1701 天前的主题,其中的信息可能已经有所发展或是发生改变。

    php 好几年了,突然觉得写文章记录很重要。一个能加深理解,一个能技术分享。看 redis 的 brpop 命令时候,突发奇想,这可以实现非争抢阻塞锁。于是有了这篇文章,看看这个锁帅不帅,欢迎拍砖。 在简书上: https://www.jianshu.com/p/6dbc44defd94

    27 条回复    2020-03-15 10:16:37 +08:00
    momocraft
        1
    momocraft  
       2020-03-14 19:55:51 +08:00
    思路不错
    如果有防意外的方案可能更好 (我猜如果进程 1 得到锁后释放前崩溃, 其他线程都要永远阻塞)
    Lax
        2
    Lax  
       2020-03-14 20:00:50 +08:00
    持🔒的进程挂掉,🔒就丢了
    kkk212
        3
    kkk212  
    OP
       2020-03-14 20:03:36 +08:00
    @momocraft 嗯嗯,是的。redis 队列 pop 空了以后队列 key 就不存在了,完整的方案还需要再想想。
    fighterlyt
        4
    fighterlyt  
       2020-03-14 20:11:28 +08:00
    这不是类似于传统的 linux 的 pid 防止并发? IT 行业已经根深叶茂了,没必要自己从 0 开始,站在巨人的肩上,才能走的更远
    kkk212
        5
    kkk212  
    OP
       2020-03-14 20:13:02 +08:00
    @Lax 是这样 还需要完善
    fighterlyt
        6
    fighterlyt  
       2020-03-14 20:17:28 +08:00
    分布式系统,所有操作,除了正常的成功、失败,还必须考虑因为网络分片等原因造成的通信中断等等问题
    kkk212
        7
    kkk212  
    OP
       2020-03-14 20:20:39 +08:00
    @fighterlyt 不局限在 id 并发业务,感觉这是并行转串行的另一种方案。有点同步消息队列的意思,epoll 思想的一种应用。
    kkk212
        8
    kkk212  
    OP
       2020-03-14 20:23:02 +08:00
    @fighterlyt 有个思路就先写出来了,用于项目还需要完善。
    23571113
        9
    23571113  
       2020-03-14 20:25:35 +08:00 via Android
    kkk212
        10
    kkk212  
    OP
       2020-03-14 20:44:02 +08:00
    @23571113 书不错
    fighterlyt
        11
    fighterlyt  
       2020-03-14 20:59:48 +08:00
    @kkk212 并发都是资源竞争
    kkk212
        12
    kkk212  
    OP
       2020-03-14 21:03:59 +08:00
    @fighterlyt 是竞争,用排队思路解决了争抢
    fighterlyt
        13
    fighterlyt  
       2020-03-14 21:35:32 +08:00
    @kkk212 资源竞争最传统的解决思路就是排队,临界区,建议锁。你这是重复造了个轮子
    kkk212
        14
    kkk212  
    OP
       2020-03-14 21:43:54 +08:00
    @fighterlyt 造轮子没啥不好,这样才能更好理解原理。不过这还没到造轮子水平,这个思路是借用 redis 的 epoll 机制和队列,实现分布式的同步排队锁。
    fighterlyt
        15
    fighterlyt  
       2020-03-14 21:46:49 +08:00
    @kkk212 还有个重要的问题,brpop 并发量大,容易导致读取错误,个人经验,忘了出处了
    kkk212
        16
    kkk212  
    OP
       2020-03-14 22:07:33 +08:00 via iPhone
    @fighterlyt 嗯嗯 这个没想到 我再看看
    pabno
        17
    pabno  
       2020-03-15 00:20:26 +08:00
    这样会导致连接一直被占用,redis 默认最大连接数为 10000,当被阻塞的连接过多的时候会影响性能吧
    lasuar
        18
    lasuar  
       2020-03-15 08:04:48 +08:00
    你这个不是锁了,而是把 redis 当做调度中间件了,只有从 list 中拿到数据的 process 才能往下执行,没有就阻塞,就类似于令牌桶算法或者 go 的 GPM 调度模型。
    kkk212
        19
    kkk212  
    OP
       2020-03-15 09:21:34 +08:00 via iPhone
    @pabno brpop 可以设置最大阻塞时间,不过太高的并发这个思路是不适合的。可以前边再加上限流。
    kkk212
        20
    kkk212  
    OP
       2020-03-15 09:22:19 +08:00 via iPhone
    @pabno 可以设置最大阻塞时间,不过太高的并发这个思路是不适合的。可以前边再加上限流。
    fighterlyt
        21
    fighterlyt  
       2020-03-15 09:29:06 +08:00
    @kkk212 如果是刚入行或者 1-2 年经验,造这个轮子很正常,但是你都几年 PHP 了,才来造这样的轮子,有点晚了
    kkk212
        22
    kkk212  
    OP
       2020-03-15 09:29:27 +08:00 via iPhone
    @lasuar 操作系统的锁或者信号量,也需要进程的阻塞和唤醒。思路是利用 redis 的 epoll 机制,做分布式的阻塞和唤醒,也有点像进程间的通信和调度。
    kkk212
        23
    kkk212  
    OP
       2020-03-15 09:34:13 +08:00 via iPhone
    令牌桶属于限流模型吧,感觉是限流和减少了并发,但是还存在并发。限流后的并发,还是需要一种解决方案。
    kkk212
        24
    kkk212  
    OP
       2020-03-15 09:41:21 +08:00 via iPhone
    @fighterlyt 不对呀,现在 php 并没有这样的轮子。令牌桶机制属于限流,限流后还会存在并发。系统调度是单机的,不是分布式的。然后消息队列是异步消费的,不是同步。
    kkk212
        25
    kkk212  
    OP
       2020-03-15 09:43:03 +08:00 via iPhone
    @lasuar 令牌桶属于限流模型吧,感觉是限流和减少了并发,但是还存在并发。限流后的并发,还是需要一种解决方案
    lasuar
        26
    lasuar  
       2020-03-15 10:05:31 +08:00
    你往深了看。
    令牌桶的原理是通过控制桶内令牌数量控制并发,相当于是一种调节 /调度机制,这种调度机制实现了限流的功能。转过来看看 brpop 这种方式,上游仍然可以通过 lpush 的频率控制下游执行的速率,这里是不是异曲同工呢,其实是实现了一样的功能,所以我说后者也是一种调度机制,用了 redis 就是做全局(分布式)的调度,同样可以不用 redis 而使用编程语言内部的队列框架实现这个机制(单机)。golang 的 GPM 模型比这个复杂一些,它的上游是操作系统(调度器),下游是 goroutine,goroutine 需要调度器分配 P(processor)和 M(内核线程)才能执行,否则就等待。
    kkk212
        27
    kkk212  
    OP
       2020-03-15 10:16:37 +08:00 via iPhone
    @lasuar 嗯嗯,相当于“调度”的一种应用,或者说分布式的进程间通信。不过令牌桶的算法是灵活限流,要是限制成比如多少 ms 放行一个进程,处理并发也不太适用。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2615 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 05:15 · PVG 13:15 · LAX 21:15 · JFK 00:15
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.