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

求教 Etcd 它没有顺序节点, 如何在实现分布式锁的时候防止惊群效应呢?

  •  
  •   BBCCBB · 2020-01-08 11:27:35 +08:00 · 3277 次点击
    这是一个创建于 1541 天前的主题,其中的信息可能已经有所发展或是发生改变。

    RT.

    27 条回复    2020-01-10 12:12:42 +08:00
    BBCCBB
        1
    BBCCBB  
    OP
       2020-01-08 11:29:14 +08:00
    google 了一波, 清一色 说通过 revision 机制.. 有大佬能具体解释下这个怎么做么...
    BBCCBB
        2
    BBCCBB  
    OP
       2020-01-08 12:11:00 +08:00
    =_=
    owt5008137
        3
    owt5008137  
       2020-01-08 13:24:38 +08:00 via Android
    它所有的 modify 都是 leader 干的。单点的而且 revision 是单调递增的。本来所有的写操作也就是要广播的惊不惊群有啥区别。
    如果是选举过程的话它是通过选举不通过随机重试时间的方式搞得,revision 版本落后就直接不批准。不知道你问得是不是这个
    BBCCBB
        4
    BBCCBB  
    OP
       2020-01-08 14:04:08 +08:00
    @owt5008137 老哥我是想问有没有像 zookeeper 实现分布式锁只用监听顺序节点的前一个节点, 前一个节点删除只用通知一个客户端, 而不是像 etcd 这样所有的都监听这个节点, 这个节点删除的时候需要通知所有监听它的客户端.
    AzadCypress
        5
    AzadCypress  
       2020-01-08 14:46:14 +08:00 via Android
    跟 zookeeper 一样的吧
    进程有个全局唯一的 id
    拿锁是写入 /lock/id
    然后获取 /lock 下的所有值
    没有 revision 比自己小的就获得锁
    否则监听 revision 比自己小的前一个 key

    好像区别就是 revision 是 kv 对象的一个属性而不在路径中
    BBCCBB
        6
    BBCCBB  
    OP
       2020-01-08 15:10:51 +08:00
    @AzadCypress 我没看到 etcd 有顺序节点这个概念或者相关的概念, 是我看漏了啥么??

    你这个意思是在 /lock 下写入自己的节点, 但每个节点 key 保证唯一, 然后按他们的 revision 来实现 zk 有序节点的概念么?
    照你这么说我想了想是可以实现了.

    但还有个问题就是这个 key 得客户端保证在所有客户端中全局唯一, 还有没有不用客户端去生成这个全局唯一得 key 的方案呀?
    AzadCypress
        7
    AzadCypress  
       2020-01-08 15:57:23 +08:00 via Android
    @BBCCBB
    etcd 是没有顺序节点的概念
    但是 etcd 有个全局的顺序 revision,不是对某个节点而是对 etcd 中所有的写入操作。

    客户端 id 的话...一个客户就对应一个 id。
    反正客户端数量有限,可以提前分好写在配置文件中。或者在启动的时候往 etcd 随便写入一个什么值拿它的 revision 肯定是唯一的。
    BBCCBB
        8
    BBCCBB  
    OP
       2020-01-08 16:21:01 +08:00
    @AzadCypress 对的,revision 是全局递增的.

    的确可以随便写一个值到目录下, 比如 uuid. 简单方便.

    这样看下来 etcd 没法自动生成顺序节点名称了, 只能客户端写入一个唯一名称的节点了
    xkeyideal
        9
    xkeyideal  
       2020-01-08 16:22:31 +08:00
    源码即文档,看一下 etcd go 的 clientv3 的代码不就行了么,官方都已经把你实现好了
    BBCCBB
        10
    BBCCBB  
    OP
       2020-01-08 16:50:21 +08:00
    @xkeyideal 大哥你看过源码 clientv3 的 mutex 源码么??? 他那个锁只是一个 cas 乐观锁,连重试都没有. cas 一下, 没获取到就返回一个 error
    xkeyideal
        11
    xkeyideal  
       2020-01-08 17:50:39 +08:00
    @BBCCBB 我还真看过,你居然会说出 etcd clientv3 里的 mutex 是乐观锁,那么建议你再重新看看代码吧,记着是 golang 版本的客户端,etcd 版本 v3.3+
    BBCCBB
        12
    BBCCBB  
    OP
       2020-01-08 18:04:47 +08:00
    @xkeyideal 我看的这个, https://github.com/etcd-io/etcd/blob/master/clientv3/concurrency/mutex.go , 大佬带带我, 我疑惑了大半天了
    xkeyideal
        13
    xkeyideal  
       2020-01-08 18:14:26 +08:00
    @BBCCBB 就是这个代码,自己先弄懂几个 revision 的含义,还有个死循环,再对比一下网上某些实现,会发现官方的分布式锁帮你把各个方面的问题全部考虑到了,至少有两种情况使用场景中出现的概率几乎为 0,人家都帮你处理了。自己动手写个使用的 demo,你就会明白了,锁的机制:大家一起抢,谁抢到算谁的,其他人不停的在等待,锁释放了,剩下的人再继续抢。看代码要仔细看,不要轻易就下结论
    xkeyideal
        14
    xkeyideal  
       2020-01-08 18:16:46 +08:00
    @BBCCBB 另外再补充一下,如果怀疑我说的,那么就动手实践,自己理解的更透彻,etcd 的大部分代码我都看过,而且还提过 pr,分布式锁和选主机制,在生产环境中都使用过,也做过多次测试,给到你的结论应该不会有问题的
    BBCCBB
        15
    BBCCBB  
    OP
       2020-01-08 18:19:14 +08:00
    @xkeyideal 😱 我再看看吧, 我就简单看了下.. 3q
    owt5008137
        16
    owt5008137  
       2020-01-08 18:22:00 +08:00 via Android
    etcd 的 watch 是按字典序和按目录层级。比如客户端只要只 watch 某个目录就不会收到其他目录的变更通知呀
    BBCCBB
        17
    BBCCBB  
    OP
       2020-01-08 18:35:01 +08:00
    @owt5008137 同一个锁是加在同一个目录下的哈
    BBCCBB
        18
    BBCCBB  
    OP
       2020-01-08 23:45:55 +08:00
    @xkeyideal 老哥,还是没看到==, 求赐教
    szkoda
        19
    szkoda  
       2020-01-09 14:12:34 +08:00
    hdr, werr := waitDeletes(ctx, client, m.pfx, m.myRev-1)
    BBCCBB
        20
    BBCCBB  
    OP
       2020-01-09 15:34:07 +08:00
    @szkoda 看到了, 我仔细研究下, 之前就过了一眼.. 3q3q.
    BBCCBB
        21
    BBCCBB  
    OP
       2020-01-09 16:32:08 +08:00
    @szkoda 多谢, 仔细看了一波, 续约, 监听目录下比他小的第一个 revision 节点, 来龙去脉都搞清楚了.

    @xkeyideal 多谢, 搞定了, 上面我说的顺序节点这个, 我看他通过`prefix+leaseId`解决了, 完美.. 甚至它还支持重入..
    BBCCBB
        22
    BBCCBB  
    OP
       2020-01-09 16:33:21 +08:00
    @xkeyideal 然后就是你说的两种不太可能出现的异常情况, 不知道是哪两种呢??
    BBCCBB
        23
    BBCCBB  
    OP
       2020-01-09 16:35:05 +08:00
    @xkeyideal 不知道 tnx 里这个 else 是不是支持重入的?如果是, 那 unlock 直接删除会不会有问题??
    xkeyideal
        24
    xkeyideal  
       2020-01-09 16:47:16 +08:00
    @BBCCBB 理解 revision 后你会发现一个,多看看 waitDeletes 你会发现另外一个,看源码要有自己的理解
    owt5008137
        25
    owt5008137  
       2020-01-10 12:07:29 +08:00 via Android
    刚看了下 go 的 client 的实现。不是还是广播给所有的 watcher 么。还是会惊群呀。
    owt5008137
        26
    owt5008137  
       2020-01-10 12:10:18 +08:00 via Android
    哦哦,我也理解错了。无视我上一条吧
    BBCCBB
        27
    BBCCBB  
    OP
       2020-01-10 12:12:42 +08:00
    @owt5008137 没广播, 它查了比它 revision 第一个小的节点, 然后监听这个节点的删除事件.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2990 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 14:50 · PVG 22:50 · LAX 07:50 · JFK 10:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.