“轮询分发”听上去很公平,但一个快一个慢的两个消费者拿到同样多的活时,慢的会拖垮整体。prefetch 怎么把它变成“谁空闲谁拿”?卡住的消费者会扣住多少消息?消费者优先级又是怎么回事?这篇都量一遍。
投递给谁(按完成顺序前 12 条): ABABABABBAAB;总计 {'A': 21, 'B': 19}队列里的消息依次轮流投给订阅它的消费者,但只投给“未确认数 < prefetch”的那些。速度相同时最终各约一半。
prefetch A 快(2 ms) B 慢(20 ms) 总耗时 0(无限) 250 350 9.37 s 100 458 142 3.75 s 10 527 73 1.90 s 1 531 69 1.83 s 理想情况(按速度比例分,没有空转)总耗时 ≈ 600 ÷ (500 + 50) 条/秒 = 1.09 s;全部均分时总耗时 ≈ 300 × 20 ms = 6.0 s
消费者速度不同、prefetch 又很大时,慢的消费者也会持有一大批消息,总耗时被它拖长(prefetch 不限时 9.37 s)。prefetch=1 或很小时,快的消费者空出来就能立刻再拿,接近按速度比例分(1.83 s)。不限 prefetch 时的分法每次运行都不一样,我没有深究原因。
prefetch A 处理完(按消息去重) 队列 (ready, unacked) = 卡住的消费者扣住的 1 499 (0, 1) 10 490 (0, 10) 100 400 (0, 100) 卡住的消费者断开(或超时)前,它手里的消息谁也拿不到;prefetch=1 时最多只有 1 条
消费者收到消息又不处理不确认,它扣住的消息正好是 prefetch 条,别的消费者拿不到。prefetch 越大损失越大。
发布速率(条/秒) A 优先级 10 B 优先级 0 20 199 1 45 108 92 80 100 100 120 100 100 速率低于 A 一个人的处理能力(约 50 条/秒)时,消息几乎都给 A;速率更高时,有些消息到达的瞬间 A 还在处理上一条(prefetch=1 已满),那些就改给 B
订阅时加参数 x-priority,数大的消费者先拿消息;只有它没空位(prefetch 已满)时才轮到优先级低的。适合做主备或“忙时溢出”。
消费者数 总耗时 每个消费者处理条数(最少~最多) 1 10.40 s 800~800 2 5.32 s 399~401 4 2.74 s 198~203 8 1.35 s 96~103
处理耗时固定、prefetch=1 时,N 个相同消费者的总耗时按 1/N 缩短,每个消费者的条数几乎相同。