quorum 队列每个队列是一个 Raft 组:leader、follower、term、日志下标到底长什么样?杀掉 leader 选举要多久?只剩一个节点时发布和读取各是什么表现?这篇用 rabbitmq-queues quorum_status 一步步看。
$ rabbitmq-queues quorum_status rq
节点 Raft 状态 Term Last Log Commit Applied
n1 leader 1 2 2 2
n2 follower 1 2 2 2
n3 follower 1 2 2 2每个 quorum 队列有自己的一个 Raft 组:一个 leader 和若干 follower(默认三个成员)。rabbitmq-queues quorum_status 给出每个成员的 Raft 状态、Term 和日志下标(Last Log、Commit Index、Last Applied)。
节点 Raft 状态 Term Last Log Commit Applied
n1 leader 1 1003 1003 1003
n2 follower 1 1003 1003 1003
n3 follower 1 1003 1003 1003
当前 leader: n1@localhost发布的消息先到 leader,作为日志条目复制给 follower,多数派落盘后提交,提交后才回 publisher confirm。平静时三个成员的下标一致。
杀掉 leader 后,第一次成功发布(confirm 回来)在 360 ms 之后
list_queues: rq | n3@localhost | [n3@localhost, n2@localhost]
节点 Raft 状态 Term Last Log Commit Applied
n1 noconnection
n2 follower 2 1008 1008 1008
n3 leader 2 1008 1008 1008leader 所在节点被杀后,剩下的成员发现没有心跳,发起选举,Term 加 1,拿到多数票的成为新 leader,本次实测 360 ms 内恢复发布。
只剩 1/3 个节点时发布一条(带 confirm),等 8 秒: 仍在等待 confirm,没有 ack 也没有 nack 同样条件 basic_get 取一条: ConnectionClosedByBroker: (541, "INTERNAL_ERROR - Cannot get a message from queue 'queue 'rq' in vhost '/'
三个成员只剩一个时写入一直挂起(没有 ack 也没有 nack),读取直接报错。quorum 队列选择一致性。
之前挂起的那条发布最终结果: ack
节点 Raft 状态 Term Last Log Commit Applied
n1 follower 3 1015 1015 1015
n2 follower 3 1015 1015 1015
n3 leader 3 1015 1015 1015
队列里最后共有 1002 条;另外之前挂起的 basic_get(auto_ack)在恢复后取走了 0 条——共发布 1000 + 1(选举后)+ 1(无多数派时)= 1002 条节点回来、追平日志后,挂起的发布得到 ack,数据一条不丢。
rq1: members = [n2@localhost] rq3: members = [n2@localhost, n1@localhost, n3@localhost] rq1: 333 ms 60126 条/秒 rq3: 396 ms 50514 条/秒
三成员比单成员慢了约 19%(396 对 333 ms 发布 20000 条),在本机回环上。