知识卡片
负载均衡与扇出两种消费模式,及确认重传导致的乱序代价
内容
多个消费者读同一主题时,有两种基本传递模式:负载均衡把每条消息只交给消费者中的一个,代理可任意分配,适合处理消息代价高、想把工作分摊到多个消费者并行处理的场景;扇出把每条消息交给所有消费者,让几个独立消费者各自”收听”同一份消息广播、互不干扰,对应批处理里多个作业读同一份输入文件的场景。两种模式可以组合:多个消费者组各自订阅同一主题,组间各收到全部消息,组内每条消息只由一个节点处理。为保证消息不因消费者崩溃而丢失,代理依赖确认机制:消费者必须显式告知代理某条消息处理完毕,代理才会移除它;如果连接断开或长时间未收到确认,代理就认为消息未处理,重新投递给另一个消费者。但确认重传和负载均衡结合后会产生一个不易察觉的副作用:假如消费者2在处理消息m3时崩溃,而消费者1此时正在处理m4,未确认的m3会被重新分发给消费者1,导致消费者1实际按m4、m3、m5的顺序处理——即使代理本身努力保持消息顺序(如JMS/AMQP标准所要求),负载均衡加重传的组合也不可避免地打乱消息顺序。如果消息之间存在因果依赖,这种乱序就是个实打实的问题;规避方法是放弃负载均衡、让每个消费者用独立队列。
参考来源
- 位置:《数据密集型应用系统设计》第十一章《流处理》"多个消费者""确认与重新传递"(源文件:_epub-src/ch11_split_000.html)
- 结论依据:原文定义负载均衡与扇出两种传递模式,说明确认机制如何在消费者崩溃后触发重传,并用消费者2崩溃导致m3被重新分配给消费者1、造成m4先于m3处理的具体例子说明负载均衡与重传组合必然导致乱序,直接支撑本卡片结论。
- 原始内容:每条消息都被传递给消费者之一……每条消息都被传递给所有消费者……消费者2在处理消息m3时崩溃,与此同时消费者1正在处理消息m4……结果消费者1按照m4,m3,m5的顺序处理消息。