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

用 redis 做分布式锁这种骚操作是怎么流行起来的?

  •  
  •   nagatoism · 2021-03-08 13:49:19 +08:00 · 21514 次点击
    这是一个创建于 1347 天前的主题,其中的信息可能已经有所发展或是发生改变。
    Redis 根本就不是设计出来干这个的,为什么网上这么多垃圾文章讲这个?

    老老实实用 ZK 或者 ETCD 不好吗?

    感觉大量的垃圾技术文章的内容都可以总结为三句

    1 我没读文档瞎 jb 用,结果不符合预期。
    2 出 bug 了受不了才老老实实读文档,原来是我用的不对。
    3 按照文章老老实实的写代码,终于对了。


    看多了会觉得中文技术社区真是垃圾堆。
    第 1 条附言  ·  2021-03-08 23:09:37 +08:00
    没发内容是我不对。但是白天毕竟是要上班的。
    首先讲一下观点。
    从分析需求开始
    1 需不需要分布式锁?
    大部分时候是不需要分布式锁的,如果你选择了 AP,那么我的理解是你可以容忍一定的数据不一致,那么你不需要分布式锁。因为一个正确性的分布式锁是很“重”的一个开销,AP 的场景一般承受不了。所以如果需要分布式锁,那么一定是一个 CP 的场景,就是说需求是为了一致性而牺牲一定的可用性。
    很多网友说,我在要求 CP 的场景用 Redis 我也没咋地。我说是,那是你命好,交的学费不够多。
    如果你一个订单 1000 万美金,你会给老板那说,我这个系统只有 0.0001 的概率会出问题,你信不信你工作没了。
    ---
    如果你有 AP 又要用到分布式锁,那请你分享一下场景和设计思路,让我们长长见识。
    这里开始我们的前提是 CP
    2 Redis 是这个场景正确的选择吗?

    首先单机 Redis 排除,因为就不是分布式锁。
    那么接下来就是 Redlock 。
    用 Martin Kleppmann 关于 Readlock 的评价
    https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html
    我擅自总结一下,
    第一段讲分布式锁的用途
    第二段讲这个算法的漏洞
    第三段讲用一个 token 做 fence 是不是就可以救回来了呢》
    第四段说不是的,因为 redis 作者做了错误的设计假设,这个系统的漏洞是无法补救的。
    就是他的假设是基于整个系统是一个半同步的状态。semi-sychornous
    这些假设对于分布式系统设计稍有涉猎就可以看出十分幼稚。
    (注意,我们的标准是 CP !)


    Redis 作者的回复我也看了。
    http://antirez.com/news/101
    很遗憾,这个兄弟基本上不懂分布式系统的理论。所以他的回答也没什么很大的价值。
    一句话,Redis 的分布式锁。你要用就要 5 个节点,那既然你都有 5 个节点了,为什么不用 ZK 和 redis 。

    3 ZK ETCD 和 redis 本质设计区别是什么?

    核心在于,ZK 和 ETCD 一开始就是为了解决分布式系统核心的共识问题( consensus )而设计开发出来的软件,Redis 不是。
    ZK 有 Zab,ETCD 有 raft 这些共识算法来解决共识问题。 不了解这些基础知识的希望了解一下。

    4 我不是研究分布式系统的博士。但是我是搞数学的。数学和分布式系统的相同点就是
    一个算法在没有数学证明之前,总是要假设它是错的。没有证明,不管多少人说是对的,也是不行的。
    5 对我的英语水平的评价不想回应。
    第 2 条附言  ·  2021-03-08 23:10:36 +08:00
    我看到有人提了说一下

    DDIA 《数据密集型程序设计》 Martin Kleppmann 著
    后端必读,京东有卖。懂得都懂。工作了看每年都有新体会。

    lamport 的论文
    Time, Clocks, and the Ordering of Events in a Distributed System
    https://lamport.azurewebsites.net/pubs/time-clocks.pdf
    开山之作,不知道不应该。

    raft 作者的博士论文,有时间可以读一下。英语很简单,把一个共识算法的细节都讲的很清楚。
    这非常了不起。
    https://web.stanford.edu/~ouster/cgi-bin/papers/OngaroPhD.pdf


    如果我提的概念你一点都没听过,兄弟听一句劝,不懂可以学,千万别不懂瞎 jb 搞。
    159 条回复    2021-03-15 20:25:20 +08:00
    1  2  
    wucao219101
        1
    wucao219101  
       2021-03-08 13:54:54 +08:00   ❤️ 52
    官方的推荐用法怎么是骚操作?
    https://redis.io/topics/distlock
    Xbluer
        2
    Xbluer  
       2021-03-08 13:55:42 +08:00   ❤️ 1
    「 Redis 根本就不是设计出来干这个的」
    看看官网这篇文章 https://redis.io/topics/distlock
    learningman
        3
    learningman  
       2021-03-08 13:56:19 +08:00   ❤️ 1
    英文这样的垃圾文章不也挺多的。。。StackOverflow 上不也那么多 Why noy Google 的问题
    wakzz
        4
    wakzz  
       2021-03-08 13:57:07 +08:00   ❤️ 1
    因为 redis 性能高哇,ZK 跟 ETCD 在高并发场景试试,分分钟成为瓶颈。

    垃圾文章确实,这几年垃圾文章暴增,各种复制粘贴水平低下,看着标题都懒得点了
    Kinnice
        5
    Kinnice  
       2021-03-08 13:58:07 +08:00
    官方推荐的
    janxin
        6
    janxin  
       2021-03-08 14:00:56 +08:00   ❤️ 3
    看来没踩过 etcd 的坑 2333
    npe
        7
    npe  
       2021-03-08 14:01:26 +08:00
    helone
        8
    helone  
       2021-03-08 14:03:14 +08:00   ❤️ 1
    别人讲的不一定是对的,但是我觉得在下结论前,可以自己试试高并发场景下 zk 、etcd 、redis 做分布式锁的优势与劣势
    fatedier
        9
    fatedier  
       2021-03-08 14:06:29 +08:00   ❤️ 10
    戾气太重~ 尽量表达自己的观点就好,很多问题都不是是非题,没有绝对答案
    qwerthhusn
        10
    qwerthhusn  
       2021-03-08 14:07:29 +08:00   ❤️ 4
    我为了一个分布式锁,要再引入一个部件??
    dqzcwxb
        11
    dqzcwxb  
       2021-03-08 14:08:12 +08:00   ❤️ 4
    你是对的
    qq1340691923
        12
    qq1340691923  
       2021-03-08 14:10:38 +08:00
    要考虑可维护性的,不能说你想用哪个组件就直接用,要看分析对各个组件的熟悉度
    672795574
        13
    672795574  
       2021-03-08 14:11:24 +08:00
    架构设计没有银弹, 只有适合业务的选型 设计 架构,不然还要架构师做什么,所有公司一套方案打天下?
    fo2w
        14
    fo2w  
       2021-03-08 14:13:06 +08:00   ❤️ 24
    一楼就下手这么重我是没想到的
    monsterxx03
        15
    monsterxx03  
       2021-03-08 14:23:10 +08:00   ❤️ 3
    有效讨论: 用 xxx 的问题在哪, yyy 在 zzz 的场景下比 xxx 强在哪里.
    无效讨论: xxx 垃圾

    回到用 redis 做锁的问题, 如果是单机 redis 用 setnx 做一个中心试锁, 在可用性要求不是特别极端的业务里未尝不可, 毕竟很多人运维的分布式系统未必有单机靠谱...

    redlock 算法争议一直有, 我是不建议用的, 印象里这个算法的争议在于依赖系统时间的一致性. 比较严谨的分布式系统一般会用 Lamport timestamp 做逻辑时间(实现上就是一个单调递增的 counter).
    bianzhifu
        16
    bianzhifu  
       2021-03-08 14:25:14 +08:00   ❤️ 9
    一楼这种动不动就上官网链接的行为(伤害性不高,侮辱性极强)
    NaVient
        17
    NaVient  
       2021-03-08 14:30:10 +08:00   ❤️ 1
    最后还鄙视下中文社区....其他的不说,哪个社区没有垃圾文章?
    kiripeng
        18
    kiripeng  
       2021-03-08 14:30:56 +08:00
    没有最好的技术,只有合适的场景。
    而且这种无效的脾气帖子,没啥软用
    swulling
        19
    swulling  
       2021-03-08 14:33:22 +08:00
    不过官方的 redlock 实现至少需要 3 个独立的 redis 实例,成本真的有点昂贵

    但是想一想 zk 或者 etcd 不也需要三个么,就感觉还好~~

    当然新的选型还是用 etcd 更合适一些,毕竟代码写起来简单,zk 就别用了
    emSaVya
        20
    emSaVya  
       2021-03-08 14:37:01 +08:00
    @bianzhifu redis 做分布式锁本来就是不合适的 官网文章很多问题 redis 作者自己都承认有漏洞
    要嘛 小公司拿个单点的 redis 随便玩玩 要嘛 老老实实 zookeeper
    liprais
        21
    liprais  
       2021-03-08 14:39:06 +08:00
    redlock 都多少年前就确认有逻辑漏洞的东西了还敢用
    emSaVya
        22
    emSaVya  
       2021-03-08 14:39:21 +08:00
    @wucao219101 再回复一下 redlock 依赖系统时钟 原理上就不适用
    cheng6563
        23
    cheng6563  
       2021-03-08 14:40:30 +08:00
    那用 MYSQL 做的呢 狗头
    KarmaWu
        24
    KarmaWu  
       2021-03-08 14:46:02 +08:00
    线上用官方推荐的 Redisson 作为分布式锁工具,暂时没有任何问题
    Yourshell
        25
    Yourshell  
       2021-03-08 14:49:46 +08:00 via Android
    怎么说呢,你的行为给这个垃圾堆多扔了一件垃圾。
    mxT52CRuqR6o5
        26
    mxT52CRuqR6o5  
       2021-03-08 14:57:38 +08:00
    不是有大佬就 redlock 到底可不可靠吵过吗,好像确实不是绝对可靠的吧
    zproo
        27
    zproo  
       2021-03-08 15:10:25 +08:00
    @wucao219101 楼主你怎么不说话😂 @nagatoism
    nagatoism
        28
    nagatoism  
    OP
       2021-03-08 15:12:53 +08:00
    @wucao219101     你这个链接拉到底就知道为什么 redlock 不可靠了
    liudaolunhuibl
        29
    liudaolunhuibl  
       2021-03-08 15:48:52 +08:00
    我觉得程序员应该向历史学家和作家学习一下,下任何结论前一定要去详细考证一下,1L 的官网链接不难找把随手谷歌一下就有了的东西也没有去考证就擅自下结论
    liprais
        30
    liprais  
       2021-03-08 15:51:00 +08:00
    @liudaolunhuibl 你显然没看过官网的这一页也没看过几年前关于 redlock 的讨论,就来指责别人没详细考证.......
    vipppppp
        31
    vipppppp  
       2021-03-08 15:53:32 +08:00   ❤️ 2
    呃在分布式 redis 下确实依赖系统时钟,有一些漏洞
    但在一些能容忍错误的情景下,我觉得 redis 分布式锁还是很适合的,毕竟如果单纯只是为了一些不重要的业务增加维护 etcd 或者 zk 集群的成本十分不值得。
    例如我主从模式下,我希望用户一段时间不要重复获取验证码,但即使他重复获取了也能够接受。

    具体情景要具体分析,一上来就喷有点离谱
    就像 python 语言在并发方面比较弱,但如果系统需要集成某些算法(人脸、NLP 等),或者各种线性代数的运算,那么它就是一个很好的选择
    opengps
        32
    opengps  
       2021-03-08 15:55:00 +08:00
    能被流行必然有某种优势,在分布式用法中,高性能的锁 redis 还真是数得上的
    intmax2147483647
        33
    intmax2147483647  
       2021-03-08 16:20:11 +08:00   ❤️ 2
    真是挺降智的,实现一个功能的途径不只有一种,在指责它的用法的时候先去总结一下这么做的优缺点,而不是一句“它设计出来就不是干这个的”。 很多东西的使用都不一定是一开始设计出来定好的,还有,一楼打脸下手很重
    Jooooooooo
        34
    Jooooooooo  
       2021-03-08 16:25:07 +08:00   ❤️ 1
    我们规模很大, 用的挺好的. (一天数千万单都用这个做锁

    真要讲, zk 才不是干这个的.
    xiangbohua
        35
    xiangbohua  
       2021-03-08 16:27:42 +08:00
    redis 作者曾经和某个分布式系统大佬 battle 过分布式锁的各种模型。所以我估计作者是有考虑过这个场景的
    zhengwenk
        36
    zhengwenk  
       2021-03-08 16:28:37 +08:00   ❤️ 1
    etcd 是 CoreOS 团队于 2013 年 6 月发起的开源项目,它的目标是构建一个高可用的分布式键值(key-value)数据库。etcd 也不是为了作为分布式锁来设计的吧。ZK 是么?所以为什么用 redis 就变成骚操作
    iseki
        37
    iseki  
       2021-03-08 16:28:56 +08:00 via Android   ❤️ 2
    redlock 存在的问题其他分布式锁依旧存在,只要它具有类似 Redlock 的特性,比如超时失效;感觉这个问题根本是逻辑上不能避免的
    iseki
        38
    iseki  
       2021-03-08 16:29:45 +08:00 via Android
    与其喷各种实现,不如想清楚自己需要什么,做出合理的选择就完了
    xiangbohua
        39
    xiangbohua  
       2021-03-08 16:30:42 +08:00
    @monsterxx03 redis 作者和某个大佬讨论了分布式锁的各种模型,被指出 redlock 存在一定几率锁失效(条件蛮极端的,好像和时间线有关系,暂时不是很清楚,大佬可以解释一下)。但是我觉得吧,小公司就别纠结这个了,那么点量,都不见得能触发这种几率
    fuis
        40
    fuis  
       2021-03-08 16:31:05 +08:00   ❤️ 1
    “看多了会觉得中文技术社区真是垃圾堆。”
    看看这楼里的回复就知道为什么中文技术社区是垃圾堆了,我挺楼主
    Rwing
        41
    Rwing  
       2021-03-08 16:33:58 +08:00   ❤️ 1
    真要讲, zk 才不是干这个的.
    dqzcwxb
        42
    dqzcwxb  
       2021-03-08 16:40:34 +08:00
    要追求性能和可靠难道不是上队列吗?分布式锁本身就是一个为了快速实现并发处理的方案,当然是有什么用什么
    v2orz
        43
    v2orz  
       2021-03-08 16:47:13 +08:00   ❤️ 1
    1.如今,redis 稍微有点规模(或者没有规模的系统)被使用的概率很高,在不想引入新组件的情况下应该算是优选方案;
    2.基于 1,在不是特别严格,不太担心小概率时间的基础上,使用 redlock,甚至 setnx 这种方案,是可以接受的,如#39
    3.使用 zk 在性能要求高的场景应该不算是一个很好的选择? Etcd 的话,同样也有别的坑存在

    个人经验来说,没有遇到要求特别严格的分布式锁场景,所以常用 redis 来做。从设计层面来说,一般也尽量规避需要分布式锁的方案
    onec
        44
    onec  
       2021-03-08 17:00:59 +08:00
    太对了哥,真的,太对了
    stach
        45
    stach  
       2021-03-08 17:10:48 +08:00   ❤️ 2
    请教一下楼主:

    1. ZK 或者 ETCD 为什么是设计来做分布式锁的, Redis 哪里不合适 ?

    2. 基于 Redis 实现分布式锁, 各个语言都有实现的开源库, 可以直接用, 官网都有链接.
    你为啥还看一堆垃圾文章, 手撸轮子呢 ?

    3. 楼主所谓的 "大量的垃圾技术文章", "中文技术社区真是垃圾堆" 是不是因为你英语不及格 ?

    如有冒犯, 请楼主 diss 回来
    vison09
        46
    vison09  
       2021-03-08 17:12:17 +08:00
    lz 脸都被打肿了,你们别锤了
    qing18
        47
    qing18  
       2021-03-08 17:16:07 +08:00
    ZK 有被设计用来做锁的,具体见论文 https://pdos.csail.mit.edu/6.824/papers/zookeeper.pdf
    liudaolunhuibl
        48
    liudaolunhuibl  
       2021-03-08 17:20:47 +08:00   ❤️ 1
    @liprais 看了,里面只有关于安全性的讨论,并没有明现的标记出不推荐使用 redlock,你说的讨论安全性等问题是指的这个把: https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html,但是 redis 作者 Antirez 写过文章来反驳这个质疑: http://antirez.com/news/101
    lxy42
        49
    lxy42  
       2021-03-08 17:21:04 +08:00   ❤️ 1
    redis 作者 antirez 和 Martin Kleppmann(DDIA 一书的作者) 关于 redlock 的讨论的相关链接:

    - redlock 原文: https://redis.io/topics/distlock
    - Martin 指出 redlck 的安全问题: https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html
    - antirez 的反驳: http://antirez.com/news/101
    nullpointerskz
        50
    nullpointerskz  
       2021-03-08 17:21:45 +08:00
    楼主虽然被打脸了,可我同意你最后一句话。
    liudaolunhuibl
        51
    liudaolunhuibl  
       2021-03-08 17:23:17 +08:00   ❤️ 1
    @liprais 另外说人家不了解的时候请带一下资料和论证,谁质疑谁举证,“redlock 都多少年前就确认有逻辑漏洞的东西了还敢用” 请把证明 redlock 有逻辑漏洞的论文或者文章的链接带上,“你显然没看过官网的这一页也没看过几年前关于 redlock 的讨论” 那你在官网上这一页往下拉一点就可以看到 antirez 对这个观点的反驳文章的链接,我都贴上了,我举证了,请你也来举证一下
    vone
        52
    vone  
       2021-03-08 17:28:13 +08:00
    Macolor21
        53
    Macolor21  
       2021-03-08 17:29:59 +08:00
    @xiangbohua 《数据密集型应用系统设计》的作者马丁
    liprais
        54
    liprais  
       2021-03-08 17:32:39 +08:00   ❤️ 1
    liprais
        55
    liprais  
       2021-03-08 17:35:24 +08:00
    @liudaolunhuibl
    https://aphyr.com/posts/283-call-me-maybe-redis
    还有这个,不过有点早了,道理是一样的
    arvinsilm
        56
    arvinsilm  
       2021-03-08 17:41:46 +08:00   ❤️ 1
    Google 搜索“redis distributed lock”,第一条结果就是官网的链接。所以楼主要么不用 Google,要么从没用英文搜索过。既然 [觉得中文技术社区真是垃圾堆] ,为什么不从“垃圾堆”里站起来?
    angkec
        57
    angkec  
       2021-03-08 17:51:08 +08:00 via iPhone
    @wucao219101 下手过重……
    ryd994
        58
    ryd994  
       2021-03-08 17:52:35 +08:00 via Android   ❤️ 1
    @lxy42 其实 ntp 不是问题。用 CLOCK_MONOTONIC 就可以,基于机器时间而无关实际时钟
    然后分布式一致性就是有 cap 问题,不可能什么都要。cap 总得适当放松一个。这里我们选择适当放松 c,仅此而已
    如果要保证 c 放弃 a 那也好办啊:不设置超时。虽然这个算法没什么用而已。
    liudaolunhuibl
        59
    liudaolunhuibl  
       2021-03-08 17:57:39 +08:00   ❤️ 1
    @liprais 你到底看没看我的回复啊,“你说的讨论安全性等问题是指的这个把: https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html” 我没贴出来?
    337136897
        60
    337136897  
       2021-03-08 18:00:18 +08:00
    被喷得好惨,围观楼主挨揍
    ryd994
        61
    ryd994  
       2021-03-08 18:00:37 +08:00 via Android   ❤️ 1
    @emSaVya
    @monsterxx03
    如果你们说的系统时钟问题是指系统时间可能前后调整,那么你们的担心是不必要的。CLOCK_MONOTONIC 是基于硬件时间,通常是开机时间,调整系统时间不影响。
    开机时间够用了,因为你不是真的在乎现在是几点几分,只是在检测时间是否流逝而已。

    @iseki “感觉这个问题根本是逻辑上不能避免的”
    正解,cap 定理决定了总得放弃一个
    bolide2005
        62
    bolide2005  
       2021-03-08 18:05:42 +08:00   ❤️ 1
    LZ 老哥一棍子要把“中文技术社区”这个垃圾堆里的人都抡倒的时候,至少也隐藏一下发过的帖子吧,真就不怕隐私泄露人肉社工啊。以及,把简历放到 GitHub 上的操作是为个啥,让人点评简历总可以放个脱敏版本的吧
    ryd994
        63
    ryd994  
       2021-03-08 18:07:19 +08:00 via Android
    @liudaolunhuibl Martin 提出的问题是真实存在的,但是是无解的。
    他提出的解决方法是无效的。
    他提出,由服务器维护一个计数器,然后 request 只有携带比当前计数器高的 token 才能被执行。

    那么问题是,谁来维护这个计数器呢?如何维护这个计数器呢?如何保证这个全局计数器的 cap 呢?如果有办法实现这个计数器,那直接找服务器要 token 不就完事了,有什么必要用另一个锁呢?

    这就有点 ex machina 的味道了。搞不定某问题,直接假设一个神奇的全局一致计数器,然后说问题解决了.
    dmcslt
        64
    dmcslt  
       2021-03-08 18:07:21 +08:00
    都博士了,你是怎么发出这个帖子的,
    pisc
        65
    pisc  
       2021-03-08 18:07:32 +08:00
    贴个 yc 的讨论好了,有感兴趣的可以去看看,我还蛮好奇这个楼有多少人是正经做分布式系统的,https://news.ycombinator.com/item?id=11065933
    karloku
        66
    karloku  
       2021-03-08 18:13:59 +08:00
    脱离场景谈方案都是耍流氓. 别人的技术文章碰到的问题就是给你在不同的场景下趟坑. 要不大家都看官方 doc 就好了.

    且和 lz 不同, 别人的"垃圾堆"文章, 在自己场景下遇到问题起码会思考一下原来自己用的不对, 而不是想都不想下个结论.
    Zzdex
        67
    Zzdex  
       2021-03-08 18:16:29 +08:00 via iPhone
    看了楼主的简历,竟然是美国的博士.....
    ryd994
        68
    ryd994  
       2021-03-08 18:23:37 +08:00 via Android   ❤️ 1
    @Zzdex 博士又怎么了。隔行如隔山。他又不是搞分布式系统的,至少简历上不是。
    但凡学过点分布式都知道分布式系统的 cap 定理。Martin 那篇文章就是外行什么都想要。
    redlock 的说明里就写了,它所提供的是有限时间的 correctness 。自己程序 gc 时间太长这是实现的问题而不是算法的问题。
    pisc
        69
    pisc  
       2021-03-08 18:34:48 +08:00
    @ryd994 全局时钟怎么到你这就便“神奇”了,我寻思着分布式系统中全局时钟不是最常见的组件之一?原来全世界分布式数据库都依赖一个“神奇”的东西呗? CAP 的问题很简单,大多数场景 C 是一定要要的,A 是 C 的前提下尽量保证,保 A 弃 C 的系统一定是要三思的,特别是基础组件,因为这把复杂性暴露给用户了,这就是为什么一谈分布式锁就无脑 redis 的毛病,因为用户有可能屁的不懂。
    nagatoism
        70
    nagatoism  
    OP
       2021-03-08 18:37:20 +08:00
    Martin 那篇文章就是外行什么都想要

    @ryd994 你比 Martin 内行,行,你赢了
    nagatoism
        71
    nagatoism  
    OP
       2021-03-08 18:38:00 +08:00
    @pisc 明白人+1. 没有 C 的分布式锁,不如一开始就不存在
    NUT
        72
    NUT  
       2021-03-08 18:44:03 +08:00
    这种瞎 jb 嘲讽的的确是 v2 的一个特色。
    哈哈哈

    哥来一次手动置顶。
    ryd994
        73
    ryd994  
       2021-03-08 18:45:40 +08:00 via Android
    @pisc 分布式系统中不存在一致的全局时钟,这是基本的基本。
    但是可以有算法实现全局一致的时间戳。但这个时间戳是只有事后才会知道。而你不可能知道现在是什么时间。
    换句话说,Martin 提出的,数据库自动拒绝无效的 token,这是无法做到的。

    实践中,分布式的储存系统可以选择 eventual consistency 。而不依赖全局锁。

    至于 cap 的取舍,这得看需求。你怎么就钦定了 a 就比 c 重要呢?小白 p 都不懂那就不该瞎 jb 用。就这么简单。用户 p 都不懂就得给用户擦屁股? redlock 那篇文章一开始就写了时间限制,自己不看说明还怪别人?
    ryd994
        74
    ryd994  
       2021-03-08 18:48:29 +08:00 via Android   ❤️ 1
    @nagatoism 然而没有 c 的分布式系统却很正常。
    你要放弃 a 或者 p 去换 c 可以。用别的算法就行了。
    我说的,martin 指出的问题是真实存在的。但他提出的解是无效的。
    如果你觉得他提出的解有效,不妨找个实现出来。即可以 reject 旧 token 的分布式储存系统。
    yzbythesea
        75
    yzbythesea  
       2021-03-08 18:51:08 +08:00
    我觉得 Redlock 不好(那篇 hackernews 的链接说得很具体)。但是你可以自己用 Redis 写一个 distributed lock manager 。不过性能不太清楚。我之前呆过的公司用的是 DynamoDB 。

    另外我觉得挂官方文档来反驳真的很 low 。
    nagatoism
        76
    nagatoism  
    OP
       2021-03-08 18:57:33 +08:00
    @ryd994 感觉你没有细看 martin 的文章。Martin 的意思是,Redis 目前的实现里缺乏实现正确分布式锁的基础设施,是救不回来的。你什么地方看出 marin 有解法的?

    redis 的作者根本不懂怎么设计分布式系统。他算法成立的前提是,系统良好,网络良好,时钟良好。但是这正是分布式系统的大忌。
    正如 yc 的一个帖子说的,在分布式系统设计里,现有证明,再有实现。没有证明的实现正确性接近于 0.
    gBurnX
        77
    gBurnX  
       2021-03-08 18:58:25 +08:00
    主要还是穷,加上科技不发达的设备性能低,不然直接 jpa 到 mysql,不香嘛。
    sprite82
        78
    sprite82  
       2021-03-08 18:59:16 +08:00
    @pisc @nagatoism 不是很理解,分布式和集群不就是为了性能问题,要让服务在某些节点挂掉之后仍然可用吗?既然要可用,P 不是最重要的吗
    liudaolunhuibl
        79
    liudaolunhuibl  
       2021-03-08 19:00:40 +08:00
    @ryd994 马丁的论点是两个:
    1. Distributed locks with an auto-release feature (the mutually exclusive lock property is only valid for a fixed amount of time after the lock is acquired) require a way to avoid issues when clients use a lock after the expire time, violating the mutual exclusion while accessing a shared resource. Martin says that Redlock does not have such a mechanism.

    2. Martin says the algorithm is, regardless of problem “1”, inherently unsafe since it makes assumptions about the system model that cannot be guaranteed in practical systems.

    你说的应该是第二个把,作者的态度是:
    I want to mention again that, what is strange about all this, is that it is assumed that you always must have a way to handle the fact that mutual exclusion is violated. Actually if you have such a system to avoid problems during race conditions, you probably don’t need a distributed lock at all, or at least you don’t need a lock with strong guarantees, but just a weak lock to avoid, most of the times, concurrent accesses for performances reasons.

    意思应该是遇到这种情况也许不需要分布式锁了,但是我没有找到你说的 token 部分,我只找到 For example you can implement Check and Set. When starting to work with a shared resource, we set its state to “`<token>`”, then we operate the read-modify-write only if the token is still the same when we write. 这段但是和你描述的有误差

    总而言之马丁的论点之一就是如果持有锁的客户端在锁过期时间之后还没有释放锁的话回有安全问题:
    In particular, the algorithm makes dangerous assumptions about timing and system clocks (essentially assuming a synchronous system with bounded network delay and bounded execution time for operations), and it violates safety properties if those assumptions are not met. Moreover, it lacks a facility for generating fencing tokens (which protect a system against long delays in the network or in paused processes).

    作者的论点是:Just a quick note. In server-side implementations of a distributed lock with auto-release, the client may ask to acquire a lock, the server may allow the client to do so, but the process can stop into a GC pause or the network may be slow or whatever, so the client may receive the "OK, the lock is your" too late, when the lock is already expired. However you can do a lot to avoid your process sleeping for a long time, and you can't do much to avoid network delays, so the steps to check the time before/after the lock is acquired, to see how much time is left, should actually be common practice even when using other systems implementing locks with an expiry.

    大概就是你应该避免客户端 A 进行长时间的工作,或者让客户端对时间进行检查:However you can do a lot to avoid your process sleeping for a long time, and you can't do much to avoid network delays, so the steps to check the time before/after the lock is acquired, to see how much time is left, should actually be common practice even when using other systems implementing locks with an expiry.

    所以我觉得马丁的论点是有道理的,但是太过于绝对了,极端情况下也许 redlock 是不安全的但是大多数情况下是可以使用的
    wangyzj
        80
    wangyzj  
       2021-03-08 19:04:53 +08:00
    强一致性会慢
    ryd994
        81
    ryd994  
       2021-03-08 19:10:34 +08:00 via Android
    @nagatoism 我理解他的话。但是这是设计系统时瞎 jb 用算法而不看说明的锅,而不是算法没有做到 promise 。我们俩的意思是一样的,但是角度不同。我的意思是这个问题无解,但是算法在适当的情况下还是可以用。你和 Martin 的意思是这个问题无解,所以应该用其他算法。

    @liudaolunhuibl 但是放弃 A 还是放弃 C,不是你所决定。具体系统设计要具体看待。
    Martin 的意思是,既然你都用上分布式锁了,你也就别指望啥性能了。A 保也是白保,不如放弃 A 保 C,搞个强一致。
    你要是能接受弱一致,大概率是不需要全局锁的。
    pisc
        82
    pisc  
       2021-03-08 19:13:50 +08:00
    @ryd994 “全局时钟”不是说真的“时钟”,因为分布式系统中,真的“时间”并不是重要,更重要的是全局递增的序列,可以是逻辑的,这个期望得到的结果是线性一致的,这是分布式数据库事务、全局自增 ID 等都强烈依赖的东西,你要是不服你自己去翻以下主流的分布式数据库和论文。分布式系统当然不一定要线性一致性,但这东西往往有强烈的趋向性和理由,比如自家的某个组件,开发人员都知道,不会去假设 safety,而是自己保证,但“分布式锁”这种东西,不保证 C,就和本地锁有强烈的区别,你没有强烈的警告意识,普通程序员不管的,即使他有幸知道这东西,但本身就不是做分布式系统出身的,不小心就会把这种复杂性带到自己系统里来了,你知道做分布式系统、并发系统最容易出错的是什么时候?觉得自己很懂,能 hold 住时序带来的复杂性。
    ryd994
        83
    ryd994  
       2021-03-08 19:24:42 +08:00 via Android
    @pisc 我上面就说了,全局时间戳是可以实现的,但全局时钟是不存在的。靠全局时间戳常见是实现最终一致性。
    你在写入的瞬间无法知道这个写入是否成功。而是只能事后再去观测系统的状态。Martin 自己都说了,这个前提是 database 能够做到 reject 过期 token,问题是怎么实现呢?如果你可以实现这一点,你从一开始就不需要分布式锁。

    我觉得一个程序员应该有阅读文档的能力并为理解一个算法的局限性。你说警告,Redis 的官方文档里是有警告的。
    littlewing
        84
    littlewing  
       2021-03-08 19:26:49 +08:00
    1 我没读文档瞎 jb 用,结果不符合预期。
    说的就是楼主你了
    ryd994
        85
    ryd994  
       2021-03-08 19:31:21 +08:00 via Android
    @sprite82 p 不是 performance,是 partition safety 。
    你说的性能问题其实并不是 cap 三者任一。或者,最多就是和 a 沾点边。但是 a 只要系统不死锁,再慢都是合格的。
    为了性能的分布式系统通常会适当放弃 C,比如设计模型就是实现最终一致性。

    然后你说的节点挂掉的问题,其实也不是绝对的。通常是保证过半节点存活时,系统还可以保证 A 。如果不过半的话真的很难保证 P 。
    miao1007
        86
    miao1007  
       2021-03-08 19:42:08 +08:00 via iPhone
    select for update 全部梭哈
    hxndg
        87
    hxndg  
       2021-03-08 19:49:38 +08:00
    @ryd994
    @pisc

    我为啥记得 martin 应该是在《数据密集型系统设计》里面就明确的说过,成功是靠观测的,你写入的瞬间是不可知的。分布式系统的麻烦里面就写了时钟是不可靠的,

    另外附上 CAP 的简单版本:一致性,可用性和分区容忍,只能三选二。
    labulaka521
        88
    labulaka521  
       2021-03-08 19:52:00 +08:00 via iPhone
    中文社区确实配不上你这个退学博士 去国外吧
    CRVV
        89
    CRVV  
       2021-03-08 19:59:04 +08:00
    @nagatoism


    > 感觉你没有细看 martin 的文章。Martin 的意思是,Redis 目前的实现里缺乏实现正确分布式锁的基础设施,是救不回来的。你什么地方看出 marin 有解法的?

    https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html#making-the-lock-safe-with-fencing

    > The fix for this problem is actually pretty simple: you need to include a fencing token with every write request to the storage service.
    pisc
        90
    pisc  
       2021-03-08 20:03:38 +08:00
    @ryd994 唉,懒得说了,感觉你对各种东西的理解都有问题,最后回你一次吧,建议你去把关于“一致性”和基础的分布式的论文都看一下,去理解个各种“一致性”的概念指的是什么,相关的模型是怎么样的。如果看完还觉得自己是对的,那你就是对的:)
    ryd994
        91
    ryd994  
       2021-03-08 20:11:43 +08:00 via Android
    @pisc 我也再最后重复一次:逻辑上全局一致的时间戳是可以实现的。linearizability 也是可以实现的。
    但是你不可能在一个分布式的储存系统里,在处理请求的瞬间就确定,这是最新的 token 。
    Martin 的文章里自己就写了。我说的和 Martin 说的不矛盾,OK ?所以他文中 making the lock safe with fencing 的方法是无效的。而他就是为了说明这个方法无效而写的这一段。
    CRVV
        92
    CRVV  
       2021-03-08 20:42:10 +08:00
    大约翻译且概括一下这两篇文章

    首先是 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,这个问题就算是解决了。


    所以核心就是第一个问题,他俩互相说对方的方案不可行,其实都没有给出能让对方认可的方案。
    我觉得吧,如果存在一个能解决这所有问题的算法,应该有人直接给出那个算法,“你这个算法不行” 太没有建设性了。
    hpeng
        93
    hpeng  
       2021-03-08 20:49:46 +08:00 via iPhone
    确实不太好啊,但是业务场景不是自己选的么,怎么选型还是根据场景来,不根据场景随便来?大部分情况 redis 够用,本着又不是不能用原则,redis 已经做得挺好的了
    xuanbg
        94
    xuanbg  
       2021-03-08 21:15:09 +08:00
    用 redis 做分布式锁,有什么毛病吗?
    CRVV
        95
    CRVV  
       2021-03-08 21:30:28 +08:00
    这个 Martin Kleppmann 在文章里大力推荐 ZooKeeper,还给了个链接
    https://curator.apache.org/curator-recipes/index.html

    然后随便点一个 Lock 进去看,都有这么一段
    Error Handling
    It is strongly recommended that you add a ConnectionStateListener and watch for SUSPENDED and LOST state changes. If a SUSPENDED state is reported you cannot be certain that you still hold the lock unless you subsequently receive a RECONNECTED state. If a LOST state is reported it is certain that you no longer hold the lock.

    说在拿到锁的情况下,如果 ConnectionState 变成了 LOST,you no longer hold the lock.
    也就是在没有释放的情况下,另一个 client 会再次拿到这个锁。
    这完全没有解决 Martin Kleppmann 提出的问题吧。
    zchlwj
        96
    zchlwj  
       2021-03-08 21:35:30 +08:00
    你说的都对
    pancl
        97
    pancl  
       2021-03-08 21:37:35 +08:00 via Android
    🌝楼主没说错啥
    nagatoism
        98
    nagatoism  
    OP
       2021-03-08 23:18:28 +08:00
    首页 回复了一下
    stabc
        99
    stabc  
       2021-03-08 23:20:50 +08:00
    为什么 redis 不能用分布式锁,你能有条理的说出来么?非要吵架一样东一句西一句?
    neoblackcap
        100
    neoblackcap  
       2021-03-08 23:30:09 +08:00
    @sprite82
    你看看 Jeff Dean 的说法就知道了,P 是必然出现的,你没有选的。只能在所谓的 A,C 中选。
    1  2  
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1128 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 19:27 · PVG 03:27 · LAX 11:27 · JFK 14:27
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.