延时队列
两个 follower 副本都已经拉取到了 leader 副本的最新位置,此时又向 leader 副本发送拉取请求,而leader副本并没有新的消息写入,那么此时 leader 副本该如何处理呢?可以直接返回空的拉取结果给follower副本,不过在 leader 副本一直没有新消息写入的情况下, follower 副本会一直发送拉取请求,并且总收到空的拉取结果,消耗资源。

Kafka 在处理拉取请求时,会先读取一次日志文件,如果收集不到足够多( fetchMinBytes ,由参数fetch.min.bytes配置,默认值为 1 )的消息,那么就会创建一个延时拉取操作( DelayedFetch )以等待拉取到足够数量的消息。当延时拉取操作执行时,会再读取一次日志文件,然后将拉取结果返回给follower副本。 延迟操作不只是拉取消息时的特有操作,在Kafka 中有多种延时操作,比如延时数据删除、延时生产等。
对于延时生产(消息)而言,如果在使用生产者客户端发送消息的时候将 acks 参数设置为 -1,那么就意味着需要等待ISR集合中的所有副本都确认收到消息之后才能正确地收到响应的结果,或者捕获超时异常。
假设某个分区有 3 个副本: leader follower1 follower2 ,它们都在分区的 ISR 集合中。不考虑 ISR变动的情况,Kafka 在收到客户端的生产请求后,将消息 3 和消息 4 写入 leader 副本的本地日志文件。
由于客户端设置了acks
-1 ,那么需要等到 follower1 follower2 两个副本都收到消息 3 和消息 4 后 才能告知客户端正确地接收了所发送的消息。如果在一定的时间内,follower1 副本或 follower2 副本没能够完全拉取到消息3 和消息 4 ,那么就需要返回超时异常给客户端。生产请求的超时时间由参数request.timeout.ms配置,默认值为 30000 ,即30s。
那么这里等待消息 3 和消息 4 写入 follower1 副本和 follower2 副本,并返回相应的响应结果给客户端的动作是由谁来执行的呢?在将消息写入leader 副本的本地日志文件之后, Kafka 会创建一个延时的生产操作(DelayedProduce ),用来处理消息正常写入所有副本或超时的情况,以返回相应的响应结果给客户端。
延时操作需要延时返回响应的结果,首先它必须有一个超时时间( delayMs),如果在这个超时时间内没有完成既定的任务,那么就需要强制完成以返回响应结果给客户端。其次,延时操作不同于定时操作,定时操作是指在特定时间之后执行的操作,而延时操作可以在所设定的超时时间之前完成,所以延时操作能够支持外部事件的触发。
就延时生产操作而言,它的外部事件是所要写入消息的某个分区的 HW (高水位)发生增长。也就是说,随着follower 副本不断地与 leader 副本进行消息同步,进而促使 HW 进一步增长, HW 每增长一次都会检测是否能够完成此次延时生产操作,如果可以就执行以此返回响应结果给客户端;如果在超时时间内始终无法完成,则强制执行。
延时拉取操作,是由超时触发或外部事件触发而被执行的。超时触发很好理解,就是等到超时时间之后触发第二次读取日志文件的操作。外部事件触发就稍复杂了一些,因为拉取请求不单单由follower副本发起,也可以由消费者客户端发起,两种情况所对应的外部事件也是不同的。如果是follower 副本的延时拉取,它的外部事件就是消息追加到了leader 副本的本地日志文件中;如果是消费者客户端的延时拉取,它的外部事件可以简单地理解为HW 的增长。
时间轮实现延时队列
 
 
Logo

Kafka开源项目指南提供详尽教程,助开发者掌握其架构、配置和使用,实现高效数据流管理和实时处理。它高性能、可扩展,适合日志收集和实时数据处理,通过持久化保障数据安全,是企业大数据生态系统的核心。

更多推荐