脑抽研究生Go并发-4-分布式并发原语-etcd、Leader 选举、分布式队列和优先级队列、分布式栅栏、STM

57 阅读4分钟

分布式并发原语

img

常用来做协调工作的软件系统是 Zookeeper、etcd、Consul 之类的软件

Zookeeper - Java

Consul 分布式并发原语一般

etcd🐂:分布式互斥锁、分布式读写锁、Leader 选举

Leader 选举

Leader + Slave

主节点常常执行写操作,从节点常常执行读操作,如果读写都在主节点,从节点只是提供一个备份功能的话,那么,主从架构就会退化成主备模式架构

通过 etcd 基础服务来实现 leader 选举

img

方法:

  • Campaign:把一个节点选举为主节点,并且会设置一个值,这是一个阻塞方法,在调用它的时候会被阻塞,直到满足下面的三个条件之一,才会取消阻塞。成功当选为主/返回错误/ctx 被取消。
  • Proclaim:重新设置 Leader 的值,但是不会重新选主
  • Resign:开始新一次选举。这个方法会返回新的选举成功或者失败的信息
  • Leader:查询当前的主节点是哪一个节点,主节点的值,版本
  • Observe:返回一个 chan,显示主节点的变动信息。

在使用的过程中,还需要做一些额外的设置,比如查询当前的主节点、启动一个 goroutine 阻塞调用 Campaign 方法,等等。

分布在不同机器中的不同进程内的 goroutine,如何利用分布式互斥锁来保护共享资源

  • 使用互斥锁的不同节点是没有主从这样的角色的,所有的节点都是一样的,只不过在同一时刻,只允许其中的一个节点持有锁。
  • Locker + Mutex + RWMutex

总结:

在使用这些分布式并发原语的时候,你需要考虑异常的情况,比如网络断掉等。同时,分布式并发原语需要网络之间的通讯,所以会比使用标准库中的并发原语耗时更长。

节点宕机,锁会释放吗?会,一定会。租约 (Lease) + 心跳 (KeepAlive) 。节点无法为租约续命,etcd 会自动删除与租约绑定的锁 Key。
读写锁有优先级吗?有,写优先。基于 Revision 的排队。一个等待中的写锁请求,会阻塞所有在它之后到达的新读锁请求,防止写操作被饿死。

分布式队列和优先级队列

img

  • NewQueue 创建队列
  • Enqueue 入队
  • Dequeue 出队

可以在一个节点将元素放入队列,在另外一个节点把它取出

  • PriorityQueue 优先级队列
  • 总结:etcd 的队列适用于低吞吐量、但对任务分发的一致性和可靠性要求极高的场景(比如 Kubernetes 的 Job 调度),而不适合用作通用的高吞吐量消息总线。

分布式栅栏

  • Barrier:分布式栅栏。如果持有 Barrier 的节点释放了它,所有等待这个 Barrier 的节点就不会被阻塞,而是会继续执行。

    • Hold 方法是创建一个 Barrier。如果 Barrier 已经创建好了,有节点调用它的 Wait 方法,就会被阻塞。
    • Release 方法是释放这个 Barrier,也就是打开栅栏。如果使用了这个方法,所有被阻塞的节点都会被放行,继续执行。
    • Wait 方法会阻塞当前的调用者,直到这个 Barrier 被 release。如果这个栅栏不存在,调用者不会被阻塞,而是会继续执行。
  • DoubleBarrier:计数型栅栏。在初始化计数型栅栏的时候,我们就必须提供参与节点的数量,当这些数量的节点都 Enter 或者 Leave 的时候,这个栅栏就会放开。

STM

事务能够保证这些更改要么全成功,要么全失败

  • 隔离级别:etcd 的 STM 提供的是可串行化 (Serializable) 的隔离级别,这是最高的隔离级别。它通过乐观锁 (Optimistic Locking)多版本并发控制 (MVCC) 来实现。

  • 工作方式 (乐观锁)

    1. 开始事务:你开始一个 STM 事务。etcd 不会在此时加任何锁。

    2. 本地读写:你在事务中进行的所有读写操作,都只是在本地的缓存中进行的。你读取的是某个特定版本(Revision)的数据快照。

    3. 提交事务 (Commit) :当你提交事务时,最关键的事情发生了

      • etcd 会检查你在事务期间读取过的所有 Key,看看它们在 etcd 中的当前版本是否和你当初读取时的版本一致
      • 如果一致 (无冲突) :说明在你操作期间,没有其他人修改过这些数据。etcd 会原子性地将你的所有写操作应用到数据库中,事务成功。
      • 如果不一致 (有冲突) :说明在你“思考”的时候,有人抢先修改了数据。etcd 会拒绝你的提交,整个事务失败
      • 重试:etcd 的 STM 客户端库通常会自动重试整个事务逻辑。