3、消息队列选型与部署:Kafka vs RabbitMQ vs Pulsar、分区与副本机制、高可用部署方案
聊到实时行情数据管道,消息队列就是整个系统的「主动脉」。我见过不少团队,一上来就选Kafka,觉得它「高大上」。结果呢?小规模行情推送,延迟高得离谱,运维成本也扛不住。说白了,选型不是选最火的,而是选最合适的。
今天我就把这三个主流消息队列掰开揉碎讲清楚。Kafka、RabbitMQ、Pulsar,它们各自擅长什么?分区和副本到底怎么玩?高可用部署有哪些坑?嗯,咱们一个一个来。
3.1 三大消息队列核心对比
先看一张总览图,我亲手画的,帮你快速建立全局认知。
这张图你看懂了吗?我简单总结一下:
- Kafka:吞吐量之王,适合海量日志和离线批处理。但延迟不是它的强项。
- RabbitMQ:延迟最低,路由最灵活。适合交易系统和实时通知。但吞吐量上不去。
- Pulsar:后起之秀,存算分离架构。扩展性和多租户是亮点。但生态还在成长。
我的建议:行情数据管道,如果每秒百万条以上,选Kafka。如果要求微秒级延迟且吞吐量不大,选RabbitMQ。如果既要吞吐又要弹性扩展,Pulsar值得一试。
3.2 分区与副本机制
分区和副本,是消息队列高可用的基石。我当年第一次搭Kafka集群,分区数设少了,结果消费者组重平衡时整个集群卡了十几秒。嗯,那教训太深刻了。
3.2.1 分区(Partition)
分区说白了就是「分而治之」。一个Topic的数据拆成多个分区,每个分区可以独立读写。这样并行度就上去了。
举个例子:行情数据Topic有10个分区,那么最多可以有10个消费者并行消费。吞吐量直接翻10倍。
经验之谈:分区数不是越多越好。我见过有人一个Topic设1000个分区,结果文件句柄爆了。一般建议分区数 = 消费者数 × 2~3倍,留点余量就行。
3.2.2 副本(Replica)
副本就是数据的「备胎」。每个分区有多个副本,分布在不同的Broker上。Leader负责读写,Follower负责同步。
一旦Leader挂了,Controller会从ISR(In-Sync Replicas)中选一个新Leader。这个过程,Kafka做得很快,但也不是没有代价。
我曾经踩过的坑:副本数设成3,但ISR里只剩1个副本。结果那个副本挂了,整个分区不可用。后来我强制要求min.insync.replicas=2,宁可写入慢一点,也不能丢数据。
来看一个Kafka的副本配置示例:
# server.properties
default.replication.factor = 3
min.insync.replicas = 2
unclean.leader.election.enable = false
# 创建Topic时指定
bin/kafka-topics.sh --create \
--topic stock-quote \
--partitions 8 \
--replication-factor 3 \
--config min.insync.replicas=2 \
--bootstrap-server localhost:9092
RabbitMQ的镜像队列和Pulsar的BookKeeper副本机制,思路类似但实现不同。RabbitMQ的镜像队列是全量复制,性能开销大。Pulsar的BookKeeper用Ensemble机制,可以做到更细粒度的副本控制。
3.3 高可用部署方案
高可用部署,说白了就是「别让单点故障搞死你」。我见过太多案例,一个Broker挂了,整个行情管道瘫痪。下面我给出三种方案的部署要点。
3.3.1 Kafka高可用部署
Kafka的高可用,核心是「多Broker + 多副本 + 避免脑裂」。
- Broker数量:至少3台,奇数台更好(配合ZooKeeper选举)
- 副本因子:至少3,min.insync.replicas=2
- ZooKeeper:独立部署,3节点起步
- 机架感知:副本分布在不同机架,防止物理故障
# 机架感知配置示例
# broker-1: rack=rack-a
# broker-2: rack=rack-b
# broker-3: rack=rack-c
# server.properties
broker.rack=rack-a
注意:Kafka 2.8+开始支持KRaft模式,不再依赖ZooKeeper。我个人建议新项目直接用KRaft,少一个组件就少一个故障点。
3.3.2 RabbitMQ高可用部署
RabbitMQ的高可用,靠的是镜像队列和Quorum队列。
- 镜像队列:所有节点同步消息,但性能差
- Quorum队列:Raft协议,性能好,推荐使用
- 节点数:3节点起步,5节点更稳
# 声明Quorum队列
rabbitmqadmin declare queue name=stock.queue \
--vhost=/ \
--arguments '{"x-queue-type":"quorum"}'
我的习惯:RabbitMQ的镜像队列我基本不用了。Quorum队列才是未来,写入性能比镜像队列高30%以上,而且自动处理脑裂。
3.3.3 Pulsar高可用部署
Pulsar的架构天生高可用。存算分离,Broker无状态,BookKeeper有状态。
- Broker:无状态,随便加,负载均衡自动做
- BookKeeper:至少3台,Ensemble Size=3,Write Quorum=2,Ack Quorum=2
- ZooKeeper:元数据存储,3节点
# BookKeeper配置
ensembleSize=3
writeQuorumSize=2
ackQuorumSize=2
# 这表示:3台Bookie存数据,写入2台就算成功,确认2台才算完成
避坑指南:Pulsar的BookKeeper磁盘IO很敏感。我曾经用机械硬盘部署,结果写入延迟飙到100ms。后来全换成NVMe SSD,延迟降到1ms以下。记住,BookKeeper一定要用SSD。
3.4 选型决策树
说了这么多,到底怎么选?我整理了一个简单的决策逻辑:
| 场景 | 推荐 | 理由 |
|---|---|---|
| 每秒百万级行情数据 | Kafka | 吞吐量碾压,磁盘顺序写无敌 |
| 微秒级交易指令 | RabbitMQ | 延迟最低,路由灵活 |
| 云原生、多租户 | Pulsar | 存算分离,扩展性好 |
| 混合负载(流+批) | Pulsar / Kafka | 两者都支持,看团队熟悉度 |
| 小团队、快速上线 | RabbitMQ | 运维简单,管理界面好用 |
你想想看,行情数据管道最怕什么?一是丢数据,二是延迟高。所以选型时,先看你的业务容忍度。如果丢一条数据可能赔几百万,那RabbitMQ的确认机制更靠谱。如果数据量大到每秒几百万条,Kafka的批量写入更合适。
最后说一句:没有银弹。我见过用Kafka做高频交易的,也见过用RabbitMQ做日志收集的。关键是你得理解每个组件的设计哲学,然后根据业务场景做取舍。嗯,这就是架构师的功力所在。