一、生产者端:防止消息发送丢失
1. 丢失场景
生产者发送消息,网络波动、broker 临时故障,消息发出去但服务端没收到,生产者无感知,直接认为发送成功,消息丢失。
2. 配置 & 方案
- acks 配置调为 all(最关键)
- acks=0:发完不管,极易丢,生产禁用
- acks=1:只等 leader 写入成功,leader 写完还没同步副本就宕机,消息丢失
- acks=all:需要分区所有 ISR 同步副本都落盘后,才返回 ack,可靠性最高
- 开启重试 retries > 0设置重试次数,发送失败自动重发;搭配
retry_backoff_ms控制重试间隔。 - 关闭异步无回调发送,做好发送结果监听同步发送 / 异步加回调,捕获异常、失败记录,本地缓存 / 落库做补发。
- 消息幂等生产者 + 事务(高可靠业务可选)
enable.idempotent=true:解决重试带来的重复发送问题- 事务:保证一批消息原子发送,要么全部成功要么全部失败,适合分布式事务场景
- 增大缓冲区、合理批量参数避免缓冲区满导致消息丢弃,配合重试兜底。
二、Broker 服务端:防止服务端存储丢失
1. 丢失场景
分区 Leader 写入消息,Follower 还没同步,Leader 机器宕机;或者磁盘故障、消息过期被清理。
2. 配置 & 方案
- 副本因子 replication-factor ≥3单个分区多副本,一份数据存多台机器,一台挂了还有其他副本。
- 保证最小同步副本 min.insync.replicas ≥2配合 acks=all 使用:ISR 列表至少保留 2 个同步副本,才允许写入消息。 防止只剩一台副本时写入,宕机直接丢数据。
- 关闭后台异步刷盘,开启同步刷盘(可选)
flush.messages=1,每条消息立即刷盘,避免数据停留在页缓存机器断电丢失; 代价是吞吐下降,大数据场景一般靠多副本兜底,不强制每条刷盘。 - 合理设置消息留存时间,不要过早删除默认 7 天,根据业务拉长留存时间;避免消费堆积没处理完,消息过期被自动删除。
- 监控 ISR 队列,防止副本长期不同步Follower 落后太多被踢出 ISR,会降低集群容错能力,及时告警修复。
三、消费者端:防止消费完消息丢失
1. 丢失场景
消费者拉取消息后,自动提交 offset,还没执行业务逻辑就宕机,offset 已经前移,重启后跳过这条消息,消息永久丢失。
2. 配置 & 方案
- 关闭自动 offset 提交
enable.auto.commit=false,改为手动提交 offset。 - 消费执行成功后再提交 offset正确流程:拉取消息 → 执行业务逻辑(入库 / 处理完成)→ 手动提交 offset。 如果业务失败,不提交 offset,下次重启重新消费这条消息。
- 使用同步提交 commitSync阻塞等待 offset 提交成功,确保 offset 持久化到 broker 再继续下一条。
- 极端兜底:业务本地落库 消息处理前先把消息持久化本地 / 数据库,处理失败可手动补发,双重保障。
四、完整生产环境可靠配置总结
- 生产者:acks=all、retries=3、开启幂等生产者;捕获发送失败记录日志重试。
- Broker:副本数 3、min.insync.replicas=2、监控 ISR 状态、延长消息保留时长。
- 消费者:关闭自动提交 offset,业务处理成功后手动同步提交 offset。
五、简短背诵版
Kafka 消息丢失分三个环节处理:
- 生产者:设置 acks=all 保证所有副本同步完成再返回确认,开启失败重试,搭配幂等生产者防止重复发送;捕获发送失败消息做补发。
- Broker 层面:每个分区配置至少 3 份副本,最小同步副本数设为 2,保证一台机器宕机还有完整数据;合理延长消息存储时间,避免未消费数据过期删除。
- 消费者端核心是关闭自动提交 offset,等业务逻辑完全处理成功后,再手动提交偏移量;如果处理失败不提交,重启会重新消费,避免消息丢失。 三层配置全部到位,才能做到理论上不丢失消息。
延伸追问备用
问:acks=all + 副本 3 一定不会丢消息吗? 答:理论几乎不会,但极端情况(ISR 内所有副本同时宕机)仍有极小概率丢失;业务层可以搭配本地消息表做最终兜底。