分布式队列
分布式队列可以简单分为两⼤类:常规的
FIFO(先⼊先出)
队列模型,
Barrier(等待队列元素聚集后统⼀安排处理执⾏)
模型。
① FIFO先⼊先出
FIFO(First Input First Output,先⼊先出),⾮常典型且应⽤⼴泛的按序执⾏的队列模型:先进⼊队列的请求操作先完成后,才会开始处理后⾯的请求。使⽤ZooKeeper实现FIFO队列,和之前提到的共享锁的实现⾮常类似。FIFO队列就类似于⼀个全写的共享锁模型,⼤体的设计思路其实⾮常简单:所有客户端都会到
/queue_fififo
这个节点下⾯创建⼀个临时顺序节点,例如如
/queue_fififo/host1-00000001
。
创建完节点后,根据如下4个步骤来确定执⾏顺序。
-
通过调⽤
getChildren()
接⼝来获取
/queue_fififo
节点的所有⼦节点,即获取队列中所有的元素。 - 确定⾃⼰的节点序号在所有⼦节点中的顺序。
- 如果⾃⼰的序号不是最⼩,那么需要等待,同时向⽐⾃⼰序号⼩的最后⼀个节点注册Watcher监听。
-
接收到Watcher通知后,重复步骤1。
② Barrier:分布式屏障
在分布式系统中,规定了⼀个队列的元素必须都集聚后才能统⼀进⾏安排,否则⼀直等待。这往往出现在那些⼤规模分布式并⾏计算的应⽤场景上,最终的合并计算需要基于很多并⾏计算的⼦结果来进⾏。这些队列其实是在 FIFO 队列的基础上进⾏了增强,⼤致的设计思想如下:
开始时,
/queue_barrier
节点是⼀个已经存在的默认节点,并且将其节点的数据内容赋值为⼀个数字n来代表Barrier值,例如n=10表示只有当
/queue_barrier
节点下的⼦节点个数达到10后,才会打开Barrier。之后,所有的客户端都会到
/queue_barrie
节点下创建⼀个临时节点,例如
/queue_barrier/host1
,如图所示。
创建完节点后,按照如下步骤执⾏。
-
通过调⽤
getData()
接⼝获取
/queue_barrier
节点的数据内容:10。 -
通过调⽤
getChildren()
接⼝获取
/queue_barrier
节点下的所有⼦节点,同时注册对⼦节点变更的Watcher监听。 - 统计⼦节点的个数。
- 如果⼦节点个数还不⾜10个,那么需要等待。
-
接受到Wacher通知后,重复步骤2