消息在队列里是先进先出的,是不是就能保证“先发先处理”?多开几个消费者、碰上 nack 重试时,顺序会怎样?想要按账户保序又要并行,该怎么设计?这篇逐项量化。
100 条,1 个消费者:处理完成的顺序前 15 个 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];相邻逆序对数 0,总逆序对数 0
同一个队列里,消息按发布顺序先进先出;一个消费者按序处理就是有序的。
消费者数 相邻逆序 总逆序对 完成顺序(前 12 个) 1 0 0 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] 2 66 68 [0, 1, 2, 4, 5, 3, 7, 6, 8, 9, 10, 11] 4 113 298 [0, 3, 4, 2, 5, 1, 9, 8, 7, 6, 10, 14] 8 109 468 [0, 5, 4, 3, 10, 9, 2, 8, 7, 6, 1, 15]
消息仍按顺序投递给不同消费者,但处理时间不同,完成顺序会乱。消费者越多越乱,实测 2 个消费者总逆序对 68,8 个 468。
处理顺序: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29] (prefetch=1 的单个消费者上 requeue 的消息被放回队首,所以顺序没有被打乱;下面用 prefetch=10 看区别) prefetch=10 的处理顺序: [0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 5, 16, 17, 18, 19, 20, 21, 22, 23, 24, 15, 26, 27, 28, 29, 25]
prefetch=1 时被 requeue 的消息回到队首,顺序不变;prefetch 较大时,被 requeue 的消息会晚于已预取的消息被处理。
处理了 1000 条;100 个账户里,每个账户内部顺序乱掉的有 0 个(按 key 分区后,同一个账户总是进同一个队列、同一个消费者) 这 100 个账户被分到 8 个队列里的分布: [12, 12, 12, 12, 12, 12, 14, 14]
要同时保序和并行,就按 key(如账户)哈希分到多个队列,每个队列一个消费者:同 key 有序,不同 key 不保证;并行度受分区数限制。