Kafka生产者原理

本文详细解析了Kafka生产者如何通过序列化、分区、幂等性和事务机制确保数据高效、一致地发送。涉及batch.size、linger.ms配置,以及事务级别acks策略,展示了Kafka在数据处理中的关键环节和技术细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Producer首先调用send方法进行发送

首先会经过拦截器,可以对数据进行一些加工处理

随后会经过序列化,kafka并没有采用Java提供的序列化器,而是自己实现的序列化器,但是Java提供的序列化器,会在原有数据的基础上,增加很多的用于安全校验的数据,在大数据的场景下,每次传输的数据量很大,如果在此基础上还要加入大量用于安全校验的数据,严重的影响了效率,所以kafka等中间件,自己实现了序列化器,仅仅进行简单的校验,增加了效率。

随后经过分区器(分区器实际上是将数据发送到了缓冲队列中,缓冲队列是一个双端队列,其内部包含内存池,避免频繁的申请和释放内存),因为kafka可以对topic进行分区,所以发送时就需要确定向哪个分区发送信息,就由分区器定义的规则来发送,一个分区对应一个队列,这些队列都是在内存中创建的,总大小默认32M,每一批次默认大小32K。

 sender线程帮助我们将缓冲队列中的数据,发送到kafka集群中。

  • batch.size:只有数据累积到batch.size之后,sender才会发送数据。默认16K
  • linger.ms:如果数据迟迟未达到batch.size,sender等待linger.ms设置的时间到了之后就会发送信息。单位ms,默认值是0ms(即默认到了就发送,不等待到达batch.size阈值)

生产环境中上面两个参数都需要调整

发送时,以分区节点为key,即broker1,broker2为key,请求为value进行发送,形成一个请求。请求发送到某个broker中,如果第一个请求发送到broker1,broker1没有即使的应答,允许继续发送第二个请求,直到五个请求都没有得到应答,后续的请求不会再发送,直到得到了请求的应答才继续发送。

kafka集群收到请求之后会涉及到一个应答机制,应答级别分为0、1、-1

  • 0:生产者发送过来的数据,不需要等待数据落盘应答
  • 1:生产者发送过来的数据,Leader(数据落盘)收到后应答,副本有没有无所谓
  • -1(all) :生产者发送过来的数据,Leader和ISR里面的所有节点收齐数据后应答,-1和all等价。
    • Leader维护了一个动态的in-sync replica set(ISR),意为和Leader保持同步的Follow + Leader集合(leader:0,ISR:0,1,2)
    • 如果Follower长时间未向Leader发送通信请求或同步数据,则该Follow将被踢出ISR。改时间阈值由replica.lag.time.max.ms参数设定,默认30s
      • 例如如果2超时,(leader:0,ISR:0,1)
    • 在生产环境中,acks=0很少使用;acks=1,一般用于传输普通日志,允许丢个别数据;acks=1,一般用于传输和钱相关的数据,对可靠性要求比较高的场景

kafka集群应答之后,如果成功,进行数据的清理,如果失败,进行重试,默认重试次数是int的最大值 


幂等性就是指Producer不论向Broker发送多少次重复数据,Broker端都只会持久化一条,保证了数据不重复

重复数据的评判标准:具有<PID,Partition,SeqNumber>相同主键的信息提交时,Broker只会持久化一条。其中PID是Kafka每次重启都会分配一个新的;Partition表示分区号;Sequence Number是单调自增的。

所以幂等性只能保证的是在单分区单会话内不重复。如果想保证数据一定不重复,就需要开启事务

使用幂等性:开启参数enable.idempotence默认为true,即默认为开启

Kafka事务原理

开启事务,必须开启幂等性

事务并不是直接存储在磁盘中,而是存储在一个特殊的topic的分区中。

 一定要手动指定事务id

  数据乱序

生产端的InFilghtRequests,默认每个broker最多缓存五个请求,当第一个数据发送过去,第二个数据没有发送成功,这时第二波数据就要进行重试,但是此时第三波数据发送,发送成功了,然后第二波数据的重试才发送成功,本来的数据顺序是123,但是现在被改为了132,发生了数据乱序

 将max.in.flight.requests-per.connection设置为1,即不缓存request请求,自然不会发生数据乱序的情况。

开启幂等性以后,因为SeqNumber是单调递增的,所以当数据是顺序的时候,不需要排序就可以发送,但是当发生上面的情况之后,服务端发现数据的SeqNumber是132,不是单调递增了,会对数据进行缓存,攒到5个以后会进行重新排序,之后再进行发送。

### Kafka 生产者 ACK 机制的工作原理 Kafka生产者 ACK(Acknowledgment)机制用于确认消息是否被成功写入到 Kafka 集群中。通过调整 `acks` 参数,生产者可以选择不同的可靠性级别以满足特定的需求。 #### 工作原理 生产者的 `acks` 参数定义了 broker 在返回确认前需要接收到的数据复制程度。以下是三种主要的 `acks` 设置及其含义: 1. **acks=0**: 当此选项启用时,生产者不会等待任何来自服务器的响应。这意味着一旦消息发送出去,就认为它已被成功接收并存储。然而,这种方式无法检测网络错误或其他异常情况,因此可能会丢失数据[^1]。 2. **acks=1 (默认)**: 在这种模式下,leader 接收到来自客户端的消息后会立即向生产者发送确认通知。不过需要注意的是,尽管 leader 节点已保存该记录,但它可能尚未将其同步给 follower 副本即返回 ack 给生产端应用[^2]。 3. **acks=all 或 -1**: 此设定要求不仅 Leader 收到了新条目,而且所有的 In-Sync Replicas(ISR)列表成员也都完成了更新操作之后才会给出回应。这样能够最大程度上保障数据的安全性与一致性,因为即使发生故障切换事件也能保证已有数据不丢弃[^3]。 #### 使用场景 - 对于那些对延迟敏感但能容忍一定程度上的数据损失的应用程序来说,“acks=0”可能是最合适的选择;因为它提供了最低延时的同时也承担着最高风险。 - 如果应用程序希望找到性能和可靠性的平衡,则应考虑采用 “acks=1”。在这种情况下,虽然不能完全消除由于Leader崩溃而导致的部分未备份数据丢失的可能性,但是大多数时候还是可以接受这样的折衷方案[^4]。 - 当绝对不允许有任何形式的数据遗失时(比如金融交易系统),则应该坚持使用“acks=-1”,这将确保只有当所有必要的副本都接受了每一条信息以后才继续下一步动作,从而达到最高的可用性和持久化水平。 ```python from kafka import KafkaProducer producer = KafkaProducer( bootstrap_servers='localhost:9092', retries=5, acks="all", # or "-1" max_in_flight_requests_per_connection=1 ) future = producer.send('my-topic', b'raw_bytes') result = future.get(timeout=60) print(result) ``` 上述代码片段展示了如何配置一个具有高可靠性的Kafka Producer实例,其中设置了`acks="all"`来确保每次发送消息都能得到所有ISRs的认可后再进行后续操作。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值