首页/数据/数据工程与 ETL 速查/生产者 acks 与持久性
Kafka64 条

生产者 acks 与持久性

acks 控制生产者在收到多少副本确认后才算写成功:0 不等确认、1 等 Leader、all 等 ISR 全部写入。持久性要求越高,延迟与失败概率越高。

acks 是什么

acks 控制生产者把「写成功」的判定放在哪一步:0 表示发送出去就返回,不等任何确认;1 表示 Leader 写入本地日志后返回;all(等价于 -1)表示 ISR 集合中的副本都写入后才返回。等级越高,持久性越好,延迟与失败概率也越高。

必须与 min.insync.replicas 配套

acks=all 单独使用并不足够:如果 ISR 里只剩一个副本,它仍然算「全部确认」。真正提供保护的是主题侧的 min.insync.replicas:当可用同步副本数低于该值时,生产者直接收到失败而不是静默降级。副本为 3 的集群通常设 2。

acks 取值对照

acks确认条件风险适用
0发送即返回,不等确认Broker 故障时消息静默丢失允许丢失的埋点、监控采样
1Leader 写入本地日志即返回Leader 宕机且未复制则丢一般业务日志
all(-1)ISR 内全部副本写入完成ISR 不足时写入直接失败账务、事件源、CDC 输出

基本信息

参数位置生产者侧配置 acks
取值范围0、1、all(或 -1)
默认值Kafka 3.0 起生产者默认 acks=all 且幂等开启
配套主题配置min.insync.replicas 决定 ISR 不足时是否拒绝写入
代价确认副本越多,延迟越高、单请求吞吐越低

典型使用场景

  • 账务与计费链路:acks=all 加 min.insync.replicas=2,宁可写入失败也不丢
  • CDC 输出主题:变更事件丢失需要重建整个下游,必须用 all
  • 埋点与监控采样:数据量极大且允许少量丢失,用 0 换吞吐
  • 一般业务日志:acks=1 在吞吐与可靠性之间取舍
  • 压测与容量评估:必须使用与生产一致的 acks 配置,否则吞吐结论无参考价值

高持久性组合

高持久性组合
# 生产者侧:等 ISR 全部确认,并开启幂等避免重试产生重复
acks=all
enable.idempotence=true
retries=2147483647
max.in.flight.requests.per.connection=5   # 幂等开启后仍可大于 1,顺序由生产者保证

主题侧配套配置

主题侧配套配置
# 副本 3 时把最小同步副本设为 2:ISR 掉到 1 个就拒绝写入,而不是静默降级
kafka-configs.sh --bootstrap-server localhost:9092 \
  --entity-type topics --entity-name orders \
  --alter --add-config min.insync.replicas=2

# 校验是否生效
kafka-configs.sh --bootstrap-server localhost:9092 \
  --entity-type topics --entity-name orders --describe
升级客户端时要注意版本差异:Kafka 3.0 起生产者默认 acks=all 且幂等开启,老版本默认是 acks=1,同样的代码在不同客户端版本上的可靠性并不相同。
配置对照:acks=all 配上 min.insync.replicas=1 等于没有额外保护,只要有一个副本在线就能写成功,副本间不同步时数据照样会丢。

易错点

  • 设置了 acks=all 但 min.insync.replicas 仍为 1,只有一个副本在线也能写入成功,持久性保护形同虚设
  • 在峰值压力下把 acks 从 all 临时改成 1 以提升吞吐,故障时静默丢数据,事后无法从 Kafka 侧恢复
  • 压测时使用与生产不同的 acks 配置,得出的吞吐上限偏高,容量规划失效
  • 误以为 acks=all 就是「消息一定不丢」:ISR 缩到单副本时若不设最小同步副本数,仍可能丢失

数据来源与参考

  • Apache Kafka 官方文档:Producer Configs(acks、enable.idempotence)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌