Kafka 作为分布式消息队列的“王者”以其极高的吞吐量和优秀的持久化能力著称。但在实际生产环境中如果配置或使用不当很容易出现消息丢失、消息重复、消息积压、频繁 Rebalance等严重问题。以下是 Kafka 在实际使用和面试中必须掌握的核心注意事项分为架构设计、生产者、消费者、消息可靠性、常见坑五个维度。一、 架构与 Topic 设计注意事项1. Partition分区数量的权衡不要太少Partition 数量决定了消费者的最大并发度。如果只有 3 个分区你启动 10 个消费者有 7 个也是闲置的。不要太多每个 Partition 对应磁盘上的一个目录和文件。分区过多会导致Broker 打开的文件句柄过多消耗内存。Controller 选举 Leader 时元数据同步变慢。客户端Producer/Consumer需要维护更多的连接和状态。建议根据预估的吞吐量来定。一般单个 Partition 的写入吞吐量在 10MB/s~50MB/s 左右。如果是高吞吐场景可以设置几十到上百个分区。2. 副本因子Replication Factor生产环境必须≥\ge≥3。副本数决定了数据的高可用性。如果副本数为 3允许 2 个 Broker 宕机而不丢数据配合min.insync.replicas2。3. 命名规范切忌随意命名。建议格式{环境}_{业务线}_{具体业务}_{版本}例如prod_order_payment_created_v1。方便后期运维和排查。二、 生产者Producer注意事项1. 保证消息不丢失ACK 机制acks0生产者发完就忘不等待 Broker 确认。性能最高极易丢消息acks1Leader 副本写入成功就返回。Leader 宕机且未同步给 Follower 时会丢消息acksall(或 -1)生产环境必选。要求所有 ISR同步副本集合中的副本都写入成功才返回。配合min.insync.replicas 2可保证强可靠性。2. 开启幂等性Idempotence与事务幂等性设置enable.idempotencetrue。Kafka 会为每个 Producer 分配一个 PID并在消息中加入 Sequence Number。Broker 端会去重防止网络抖动导致 Producer 重试时产生重复消息解决单 Partition 内的 Exactly Once。事务如果消息需要跨多个 Partition 发送且要求要么全成功要么全失败必须开启 Kafka 事务initTransactions()。3. 提升吞吐量批量与压缩批量发送调整batch.size默认 16KB和linger.ms默认 0ms建议设为 5~50ms。让 Producer 稍微等一等凑够一批再发极大减少网络请求次数。开启压缩设置compression.typelz4或snappy。在 Producer 端压缩Broker 端保持压缩Consumer 端解压。能大幅节省网络带宽和磁盘 IO。4. 顺序消费问题Kafka只能保证单个 Partition 内的消息有序无法保证全局有序。如果业务要求同一个订单的消息必须有序必须在发送时指定相同的 Key如 OrderId利用Key的 Hash 值将消息路由到同一个 Partition。三、 消费者Consumer注意事项1. 消费组与 Partition 的关系一个 Partition只能被同一个 Consumer Group 中的一个Consumer 消费。避坑Consumer 的数量不要超过Partition 的数量。多出来的 Consumer 会处于闲置状态Idle白白浪费资源。2. 偏移量Offset提交策略核心自动提交enable.auto.committrue默认每 5 秒提交一次。极易导致消息丢失或重复消费。因为拉取消息和提交 offset 是异步的如果拉取了消息还没处理完就宕机了重启后会从旧 offset 开始导致重复消费如果处理完了但还没到提交时间就宕机了会导致丢失。手动提交推荐设置enable.auto.commitfalse。在业务逻辑完全处理成功后再调用commitSync()或commitAsync()提交 offset。3. 警惕 Rebalance重平衡Rebalance 会导致所有消费者暂停消费STW, Stop The World对吞吐量影响极大。触发条件消费者组成员变化宕机/新增、订阅的 Topic 数量变化、Partition 数量变化。避坑假死导致的 Rebalance如果消费者处理消息太慢超过了max.poll.interval.ms默认 5 分钟Broker 会认为该消费者“死了”将其踢出组触发 Rebalance。解决适当调大max.poll.interval.ms或者减小max.poll.records每次拉取的消息条数让每次处理的任务量变小。四、 消息“零丢失”终极方案面试必考要保证消息从生产到消费绝对不丢失需要三管齐下Producer 到 Broker 不丢acksallretries Integer.MAX_VALUE无限重试min.insync.replicas 2至少 2 个副本写入成功Broker 自身不丢副本数≥\ge≥3。设置unclean.leader.election.enablefalse关键。默认情况下如果 Leader 挂了Kafka 会从 ISR 中选新 Leader。如果 ISR 全挂了默认是不允许从非 ISR可能数据有延迟中选 Leader 的宁可停机也不丢数据。如果设为 true虽然能恢复服务但会导致数据丢失。Broker 到 Consumer 不丢关闭自动提交 Offset。先处理业务逻辑成功后再手动提交 Offset。消费端必须实现接口幂等性防止重复消费。五、 常见坑与生产事故处理1. 消息积压几千万条堆积怎么办原因消费者处理太慢或下游数据库/接口故障。紧急处理方案临时扩容修复消费者 Bug 或恢复下游服务。如果原 Topic 只有 10 个 Partition消费者已经拉满。此时新建一个 Topic设置 60 个 Partition。部署一个临时的“转发程序”原 Consumer它只负责从原 Topic 拉取消息不做任何业务处理直接轮询分发到新 Topic 的 60 个 Partition 中。启动 60 个新的 Consumer 消费新 Topic并行处理业务。积压处理完毕后恢复原状。2. 消息体过大导致发送失败Kafka 默认限制单条消息大小为1MB。如果发送 JSON 或包含图片 Base64 的大消息会报错RecordTooLargeException。解决治本大文件/大对象不要直接放 Kafka应该上传到 OSS/MinIOKafka 里只传 URL。治标如果必须传需要同步修改 Producer 的max.request.size、Broker 的message.max.bytes和replica.fetch.max.bytes以及 Consumer 的fetch.message.max.bytes。3. 延迟消息支持Kafka原生不支持延迟消息像 RocketMQ 那样。替代方案使用多个不同延迟级别的 Topic如delay_1s,delay_5s配合定时任务将消息转移到下一个级别的 Topic。在 Consumer 端拉取后判断时间戳如果没到时间利用线程池的DelayQueue或ScheduledExecutorService在内存中延迟处理不推荐容易丢。引入外部组件如结合 Redis 的 ZSet 或 RocketMQ。六、 总结与选型建议Kafka适合大数据日志收集、流式计算、超高吞吐的场景如 ELK 架构、Flink 数据源。它的强项是吞吐量但在低延迟和复杂路由上不如 RocketMQ。RocketMQ适合核心业务链路、金融级交易、需要丰富消息类型延迟、事务、顺序的场景。RabbitMQ适合中小型公司、对路由规则要求复杂、对消息可靠性要求极高但吞吐量要求不是千万级的场景。在实际使用中“手动提交 Offset 消费端幂等”是 Kafka 消费端的黄金法则而“acksall min.insync.replicas2”是生产端的黄金法则。牢记这两点能避开 90% 的 Kafka 生产事故。