【kafka系列】At Least Once语义

目录

[1. At-Least-Once语义的定义](#1. At-Least-Once语义的定义)

[2. Kafka实现At-Least-Once的机制](#2. Kafka实现At-Least-Once的机制)

[2.1 生产者端](#2.1 生产者端)

[2.2 消费者端](#2.2 消费者端)

[3. At-Least-Once示例](#3. At-Least-Once示例)

场景描述

[3.1 生产者代码(可能重复发送)](#3.1 生产者代码(可能重复发送))

[3.2 消费者代码(可能重复处理)](#3.2 消费者代码(可能重复处理))

[4. 典型重复场景分析](#4. 典型重复场景分析)

场景1:生产者重试导致消息重复

场景2:消费者重复处理消息

[5. 业务端如何应对重复](#5. 业务端如何应对重复)

[5.1 幂等性处理](#5.1 幂等性处理)

[5.2 消费者端去重](#5.2 消费者端去重)

[6. At-Least-Once vs Exactly-Once](#6. At-Least-Once vs Exactly-Once)

[7. 总结](#7. 总结)


1. At-Least-Once语义的定义

At-Least-Once(至少一次) 语义指:

  • 消息从生产者到Broker:确保消息至少成功写入一次(可能因重试导致重复)。
  • 消息从Broker到消费者:确保消息至少被消费一次(可能因消费者重复拉取导致处理多次)。

核心特点消息不丢失,但可能重复


2. Kafka实现At-Least-Once的机制

2.1 生产者端
  • 配置 acks=all:确保消息被所有ISR副本写入后才返回成功。
  • 开启重试( retries > 0**)**:若Broker未及时响应,生产者自动重试发送消息。
  • 风险:若Broker已写入但未返回ACK(如网络超时),生产者重试会导致消息重复。
2.2 消费者端
  • 手动提交Offset :消费者处理完消息后手动调用commitSync()提交Offset。
  • 风险:若消费者处理消息后崩溃,未提交Offset,下次启动时会重新拉取消息,导致重复处理。

3. At-Least-Once示例

场景描述

一个用户积分系统:

  • 生产者 :发送用户积分增加消息到Topic user_points
  • 消费者 :消费消息,为用户增加积分,并提交Offset。
    要求:积分必须至少增加一次(允许重复增加,但需业务端处理重复)。

3.1 生产者代码(可能重复发送)
java 复制代码
// 生产者配置(At-Least-Once)
Properties props = new Properties();
props.put("bootstrap.servers", "kafka1:9092");
props.put("acks", "all");      // 确保消息写入所有ISR副本
props.put("retries", 3);       // 重试3次

KafkaProducer<String, String> producer = new KafkaProducer<>(props);

// 发送积分消息(可能重复)
producer.send(new ProducerRecord<>("user_points", "user-1001", "+10"));

潜在问题

若Broker写入成功但网络超时,生产者重试会导致消息重复发送到Topic。


3.2 消费者代码(可能重复处理)
java 复制代码
// 消费者配置(At-Least-Once)
Properties props = new Properties();
props.put("bootstrap.servers", "kafka1:9092");
props.put("group.id", "points-group");
props.put("enable.auto.commit", "false"); // 关闭自动提交

KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
consumer.subscribe(Collections.singletonList("user_points"));

while (true) {
    ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
    for (ConsumerRecord<String, String> record : records) {
        // 处理消息:为用户增加积分
        addUserPoints(record.key(), Integer.parseInt(record.value()));
        // 手动提交Offset(可能失败)
        consumer.commitSync();
    }
}

潜在问题

addUserPoints()执行成功但commitSync()失败(如消费者崩溃),下次启动时会重新拉取并处理同一消息,导致积分重复增加。


4. 典型重复场景分析

场景1:生产者重试导致消息重复
  • 原因:Broker已写入消息但ACK丢失,生产者重试发送。
  • 结果 :Topic中存在两条相同消息(如user-1001, +10)。
场景2:消费者重复处理消息
  • 原因:消费者处理消息后未提交Offset(如崩溃)。
  • 结果:重启后重新拉取并处理同一消息,积分被重复增加。

5. 业务端如何应对重复

5.1 幂等性处理
  • 数据库唯一约束:为每条消息生成唯一ID,插入时去重。
sql 复制代码
INSERT INTO user_points (user_id, points, msg_id) 
VALUES ('user-1001', 10, 'uuid-123') 
ON CONFLICT (msg_id) DO NOTHING;
  • 业务逻辑幂等:设计接口支持多次调用结果一致。
java 复制代码
// 幂等积分增加方法
public void addPoints(String userId, int points, String msgId) {
    if (!isMessageProcessed(msgId)) {
        updateUserPoints(userId, points);
        markMessageAsProcessed(msgId);
    }
}
5.2 消费者端去重
  • 本地记录已处理消息:使用缓存或数据库记录已处理的Offset或消息ID。
java 复制代码
// 消费者处理逻辑(伪代码)
for (ConsumerRecord record : records) {
    if (!processedMessages.contains(record.offset())) {
        addUserPoints(record.key(), record.value());
        processedMessages.add(record.offset());
        consumer.commitSync();
    }
}

6. At-Least-Once vs Exactly-Once

|--------|-------------------|-----------------------|
| 特性 | At-Least-Once | Exactly-Once |
| 消息丢失风险 | 不丢失 | 不丢失 |
| 消息重复风险 | 可能重复 | 不重复 |
| 性能开销 | 低(无需事务) | 高(事务与协调开销) |
| 适用场景 | 允许重复的业务(如日志采集) | 金融交易、精准统计 |
| 实现复杂度 | 简单 | 复杂(需生产者、Broker、消费者协同) |


7. 总结

  • At-Least-Once是Kafka的默认语义 :通过acks=all和手动提交Offset实现,简单高效。
  • 业务端必须处理重复:通过幂等性设计或去重机制避免数据不一致。
  • 适用场景:日志采集、指标上报等允许少量重复但对丢失敏感的场景。

通过合理配置和业务设计,At-Least-Once可平衡可靠性与性能,是大多数场景的推荐选择。

相关推荐
小淮AI4 小时前
国际教育课程的本土化探索:以枫叶教育三十年为观察样本
大数据·人工智能
城管不管4 小时前
重生——第十一次面试之挖财一面2026.8.19已OC
java·服务器·jvm·数据库·spring·面试·职场和发展
倔强的石头1064 小时前
向量数据库从相似度检索走向融合数据底座
数据库
龙兵AI增长破局圈.赵老师讲成交5 小时前
只有把过程管好,结果才会出来。
大数据·人工智能·ai·创业创新
今天AI了吗6 小时前
Python 基础语法(一):常量、变量、输入输出与运算符
开发语言·数据库·人工智能·python·sql·深度学习·机器学习
qq407855606 小时前
面向智能补货需求的进销存系统盘点
大数据·人工智能·低代码·制造
CHENGQUAN_kenan6 小时前
佛山亚马逊卖家出口退税合规指南|9610免税、一般贸易退税、无票采购、申报误区全覆盖
大数据·经验分享·笔记·百度
Web3_Daisy6 小时前
从流动性到执行:如何降低 MEV 对 Web3 市场
大数据·人工智能·web3·区块链
日常通勤穿搭6 小时前
电商 AI 作图用哪个最方便?新手商家 AI 出图工具对比
大数据·人工智能
lilian2337 小时前
Harmony os 技术实战|拼豆制图27:用单字符编码承载 50 张 70×70 图纸
前端·数据库·华为·harmonyos