2. 消息队列选型与部署:Kafka核心概念与高可用实战

大家好,我是老张。今天咱们聊聊Kafka。

做实时数据管道,消息队列是绕不开的坎。市面上选择很多,RabbitMQ、Pulsar、RocketMQ……但我个人习惯,只要吞吐量要求高、日志类数据多,首选就是Kafka。为什么?说白了,它天生就是为海量数据设计的。

我记得刚入行那会儿,公司选型时争论了很久。后来压测一跑,Kafka的吞吐量是RabbitMQ的十几倍。嗯,从那以后,我就再也没换过。

2.1 Kafka核心概念:Topic、Partition、Consumer Group

这三个概念,你搞懂了,Kafka就入门了一半。

2.1.1 Topic(主题)

Topic就是数据的分类。好比一个快递站,不同区域的包裹放在不同的货架上。你发一条订单数据,就往“订单Topic”里扔;发一条日志,就往“日志Topic”里扔。

每个Topic可以有多个生产者往里写数据,也可以有多个消费者读数据。互不干扰。

2.1.2 Partition(分区)

这是Kafka实现高吞吐的关键。一个Topic会被拆成多个Partition,每个Partition是一个有序的、不可变的日志文件。

为什么要分区?你想想看,如果只有一个文件,所有数据都往里面写,那速度肯定慢。分区之后,多个生产者可以同时往不同分区写,消费者也可以并行读。吞吐量自然就上去了。

重要: Partition内的消息是有序的,但Partition之间不保证全局有序。如果你需要严格有序,那就只能设一个Partition——但吞吐量会下降。这是典型的trade-off。

2.1.3 Consumer Group(消费者组)

这是Kafka最巧妙的设计之一。一个Consumer Group里的消费者,共同消费一个Topic的数据。每个Partition只能被组内的一个消费者消费。

举个例子:你有一个Topic有4个Partition,Consumer Group里有3个消费者。那就会有一个消费者消费2个Partition,另外两个各消费1个。如果消费者增加到4个,那就一人一个Partition。如果增加到5个,那就有一个人闲着。

我的经验: 我曾经在生产环境遇到过消费者组内成员频繁加入退出,导致rebalance风暴。整个消费链路卡了十几分钟。后来我加了个参数:session.timeout.ms 调大到30秒,配合 max.poll.interval.ms 控制,才稳定下来。

2.2 Kafka集群部署与配置

单机Kafka玩玩可以,生产环境必须上集群。我建议至少3台Broker起步。

2.2.1 基础架构

一个Kafka集群由多个Broker组成。每个Broker就是一台服务器。ZooKeeper(或KRaft模式)负责协调。

数据写入时,生产者指定Topic和Partition。Broker收到后,写入本地磁盘,并同步到副本。

2.2.2 关键配置参数

参数名 推荐值 说明
num.partitions 3-10(根据吞吐量调整) Topic默认分区数。我一般设6个起步
default.replication.factor 3 副本数。3副本可以容忍1台Broker宕机
log.retention.hours 168(7天) 数据保留时间。根据磁盘容量调整
message.max.bytes 10485760(10MB) 单条消息最大大小。别设太大,否则网络压力大
避坑指南: 我曾经把 log.retention.bytes 设得太小,结果数据频繁被删除,消费者追不上。后来我改成按时间保留,配合监控告警,才解决问题。

2.2.3 部署步骤(简化版)

# 1. 下载解压
wget https://downloads.apache.org/kafka/3.5.0/kafka_2.13-3.5.0.tgz
tar -xzf kafka_2.13-3.5.0.tgz

# 2. 修改配置 server.properties
# broker.id=1(每台机器不同)
# listeners=PLAINTEXT://0.0.0.0:9092
# advertised.listeners=PLAINTEXT://你的IP:9092
# log.dirs=/data/kafka/logs
# zookeeper.connect=zk1:2181,zk2:2181,zk3:2181

# 3. 启动
bin/kafka-server-start.sh config/server.properties &

嗯,这里要注意:advertised.listeners 一定要配成客户端能访问的IP。我见过有人配了localhost,结果远程客户端连不上,排查了半天。

2.3 Kafka高可用机制

Kafka的高可用,靠的是副本机制和ISR(In-Sync Replicas)。

2.3.1 副本机制

每个Partition可以有多个副本。其中一个叫Leader,负责读写。其他叫Follower,负责同步。

Leader挂了怎么办?Controller会从ISR里选一个新的Leader。ISR就是所有与Leader保持同步的副本列表。

核心: 生产者写入时,可以设置 acks 参数:
  • acks=0:不等待确认,最快但可能丢数据
  • acks=1:Leader确认即可,中等可靠性
  • acks=all:所有ISR副本都确认,最安全但最慢
我生产环境一般用 acks=all,配合 min.insync.replicas=2,保证至少2个副本同步。

2.3.2 故障恢复流程

假设一个Partition有3个副本,Leader在Broker1上。Broker1突然宕机了。

  1. Controller检测到Broker1心跳超时
  2. Controller从ISR中选出一个新的Leader(比如Broker2上的副本)
  3. 生产者、消费者更新元数据,开始读写新Leader
  4. Broker1恢复后,作为Follower重新加入ISR

整个过程通常在几秒内完成。你想想看,如果业务能接受秒级中断,那Kafka的高可用完全够用。

我的建议: 别把 unclean.leader.election.enable 设为true。这个参数允许非ISR副本成为Leader,虽然能快速恢复,但可能丢数据。除非你明确知道自己在做什么,否则别碰。

2.3.3 生产环境高可用 checklist

  • Broker数量至少3台,分散在不同机架或可用区
  • 副本因子设为3,min.insync.replicas 设为2
  • 生产者设置 acks=all,重试次数适当(我一般设3次)
  • 消费者设置 enable.auto.commit=false,手动提交offset
  • 监控Broker的磁盘、网络、GC情况

我记得有一次,集群里一台Broker的磁盘快满了,导致写入性能急剧下降。还好监控告警及时,我赶紧扩容了磁盘。从那以后,我养成了每周检查磁盘使用率的习惯。

好了,Kafka的核心概念、部署和高可用机制就聊到这儿。下一章咱们讲讲Kafka的监控和调优,到时候我会分享一些压测数据,看看不同配置下性能到底差多少。


公众号:蓝海资料掘金营,微信deep3321