消息队列:先分清用途,再比较 Kafka 和 RocketMQ
「高并发就上消息队列」把三件事情合成了一句。
解耦是主流程不需要等下游返回。发短信时,主流程把消息交出去就可以结束。短信服务短时间不可用,不该把下单失败一起带上。
削峰是下游接不住瞬时流量。100 个请求同时进来,处理能力只有 10,就先进入队列,按下游的速度消费。队列没有把工作变少,它把失败从「立刻打挂」变成「延迟处理」。
分发是一份变更要通知多个互不相知的消费者。用户资料更新后,几个模块各自改自己的缓存。发一条消息,订阅了的各自处理。在 Kafka 里,这条消息不会因为被一个消费者取走就消失。
选型时先看约束。吞吐和扩展要求高,RocketMQ 和 Kafka 都在候选里。主题数量很大时,按主题规模选,不按基准测试的第一名选。功能和性能都够,选团队已经会部署、会排障的那个。我更熟悉 Kafka。RocketMQ 的差别主要是主题容量更大,死信队列这类能力是现成的。
Kafka 的速度来自三条路径,不是来自某一台机器更快。发送时把多条消息打成一批,还可以压缩,减少网络往返和磁盘写入的次数。存储时顺序写磁盘,读的时候先经过操作系统的页缓存。消费时一次拉取多条,不同分区由不同消费者并行处理。
Topic 是逻辑名字。真正写到磁盘上的是 Partition,所以分区是物理的。一个业务一个主题仍可能太大,分区是为了把同一个主题再拆开。每个分区有一个 leader 处理读写,follower 复制,用来在节点故障时继续服务。分区落在哪台 Broker 上,先随机放 0 号分区,其余按 Broker 顺序往后排,排到头再绕回。
消费者组用来在成员变化时重新分配分区。有人加入或退出,就做一次再平衡,让每个消费者拿到的分区尽量均匀。没有这一步,退出的那个消费者名下的分区就没有人读。