1
2 客户端写入参数。
batch.size
通过这个参数来设置批量提交的数据大小,默认是16k,当积压的消息达到这个值的时候就会统一发送(发往同一分区的消息)
linger.ms
这个设置是为发送设置一定是延迟来收集更多的消息,默认大小是0ms(就是有消息就立即发送)
满足上述任意一条件即发送消息。
注: 如果批量16K或者时间大于0, 会有消息延迟。 需视情况设置。默认是立即发送
3 生产者基本逻辑:
Producer producer = new KafkaProducer(props) 和 producer.send(msg, callback)
在创建 KafkaProducer 实例时,生产者应用会在后台创建并启动一个名为 Sender 的线程,该 Sender 线程开始运行时首先会创建与 Broker 的连接。
1)初始化TCP连接
bootstrap.servers 参数。它是 Producer 的核心参数之一,指定了这个 Producer 启动时要连接的 Broker 地址。请注意,这里的“启动时”,代表的是 Producer 启动时会发起与这些 Broker 的连接。因此,如果你为这个参数指定了 1000 个 Broker 连接信息,那么很遗憾,你的 Producer 启动时会首先创建与这 1000 个 Broker 的 TCP 连接。
2)元数据更新TCP连接
场景一:当 Producer 尝试给一个不存在的主题发送消息时,Broker 会告诉 Producer 说这个主题不存在。此时 Producer 会发送 METADATA 请求给 Kafka 集群,去尝试获取最新的元数据信息。然后刷新连接
场景二:Producer 通过 metadata.max.age.ms 参数定期地去更新元数据信息。该参数的默认值是 300000,即 5 分钟,也就是说不管集群那边是否有变化,Producer 每 5 分钟都会强制刷新一次元数据以保证它是最及时的数据
3)关闭TCP连接
a)主动关闭实际上是广义的主动关闭,
调用 kill -9 主动“杀掉”Producer 应用。当然最推荐的方式还是调用 producer.close() 方法来关闭
b)被动关闭(客户端发起连接,Broker 端关闭)
与 Producer 端参数 connections.max.idle.ms 的值有关。默认情况下该参数值是 9 分钟,即如果在 9 分钟内没有任何请求“流过”某个 TCP 连接,那么 Kafka 会主动帮你把该 TCP 连接关闭。
用户可以在 Producer 端设置 connections.max.idle.ms=-1 禁掉这种机制。一旦被设置成 -1,TCP 连接将成为永久长连接。当然这只是软件层面的“长连接”机制,由于 Kafka 创建的这些 Socket 连接都开启了 keepalive,因此 keepalive 探活机制还是会遵守的(TCP socket定期默认2小时会发送信号检测对方,保持继续连接,或者异常重新连接,或者检测不到关闭)。
4 写入确认过程
发送确认
acks=0
:如果生产者能够通过网络把消息发送出去,那么就认为消息已经成功写入Kafka- 如果分区离线或者整个集群长时间不可用,那么就不会收到任何错误
- 即使在完全首领选举的情况下,仍有可能丢失消息,因为在新首领选举过程中,生产者并不知道首领已经不可用了
- 在该模式下,运行速度是非常快的,可以得到惊人的吞吐量和带宽利用率,但会丢失一些数据
acks=1
:首领在收到消息并把它写入到分区数据文件(Linux文件系统缓存)时返回确认或错误响应- 在该模式下,如果发生正常的首领选举,生产者会在选举时收到
LeaderNotAvailableException
异常 - 如果生产者能够恰当地处理该异常,那么它就会重试发送消息,最终消息会安全到达新首领
- 但仍有可能丢失数据,例如消息已经成功写入首领,但在消息被复制到跟随者副本之前首领发生崩溃
- 在该模式下,如果发生正常的首领选举,生产者会在选举时收到
acks=all/-1(
在0.9.0以前的版本,是用-1表示all):首领在返回确认或者错误响应之前,会等待所有同步副本都收到消息- 如果和
min.insync.replicas
结合,就能决定在返回确认前至少有多少个副本能够收到消息 - 这是最保险的做法,生产者会一直重试直到消息被成功提交
- 但这也是最慢的做法,生产者在继续发送其他消息之前需要等待所有副本都收到当前的消息
- 可以通过使用异步模式和更大的批次来加快速度,但这样通常会降低吞吐量
- 如果和
5 副本同步过程。
ifollower副本同步
follewer副本只做一件事情:向leader副本请求数据。
术语:
起始位移(base sffset):表示副本当前第一条消息的offset。
高水印值(high watermark,HW):副本高水印值。是指ISR中min.insync.replicas指定数量的
节点都已经复制完的消息的offset。也是消费者所能获取到的消息的最大offset。超过HW值的所有消息被视为“未提交成功的”,因而consumer是看不到的。
日志末端位移(log end offset,LEO):副本 日志中下一条待写入消息的offset。
当生产者发布消息到topic的某个分区时,消息首先被传递到leader副本,然后follower副本向leader副本请求消息,leader副本所在的broker推送消息给follower副本,一旦有足够的副本收到消息,leader就会提交这个消息(ISR中副本同步完成,ack=-1情况下),消费者就能消费到这个消息了。
如果副本发生故障,leader会把他从isr中剔除,那如果follower重启后呢?follower重启后会去leader上恢复最新的HW并将日志截断到HW,并继续从leader中获取HW以后的消息,一旦完全赶上leader,副本将被重新加入到ISR队列中,系统将重新回到fully replicated模式。
那如果leader发生故障呢,其他follower会争相竞争做leader,最终只有一个follower竞争成功升级成为leader,故障leader重启后成为follower去新leader同步消息。