Flink kafka connectors 源码详解---<1>

本文详细解析Flink连接Kafka作为数据源时,SourceCoordinator如何管理topic分区,如何根据并行度进行分区分配,以及动态分区更新和watermark的生成机制。通过源码分析,阐述了KafkaSourceEnumerator的角色以及工作流程。
摘要由CSDN通过智能技术生成

先抛几个简单问题,1问, 4个topic,每个topic 5个分区,问并行度10 ,这个并行度是怎么划分这些topic 分区的。2问,topic 分区 动态更新怎么做的。3问,就1问中的tm 是怎么产生的?

省流版,先总结。Flink 中kafka 作为Source源头,首先会开始一个SourceCoordinator来与Kafka联系获取所有topic分区,同时兼顾新增tp(topic parition)的检测,在根据并行度,根据一个规则(等下用源码展示这个规则)来切分tp,然后,Flink 在并行度work中会开启SourceOperator,并向SourceCoordinator发送注册请求,要求获取split tp,用来后续的消费kafka数据。其中会创建KafkaSourceReader,该对象主要是用来创建KafkaPartitionSplitReader,以及SplitState的管理。而KafkaPartitionSplitReader就是最实际用来与Kafka建立consumer来消费数据的。

先贴上规则,见以下代码,可以明显看出,同一个topic,同属于一个startIndex,但是会根据不同的partion,又被切分到不同的地方。
那就可以回答问题1,同一个topic的5个分区要平分到并行度为10的work内,如果,该topic的startIndex=0;那么这5个分区依次分到0、1、2、3、4 的work上,进行数据获取。所以,这个并不会存在一个KafkaConsumer 消费 同一个topic的5个分区,但是有可能存在 一个KafkaConsumer 消费不同topic的不同分区,因为startIndex是不定的,partion会重叠划分到相同work上。如果,并行度<5,才会出现同一个KafkaConsumer 消费同一个topic的不同分区。这里有个前提是不同的work 代表不同的KafkaConsumer,这是肯定的,因为不同的work,就意味的并行度。

static int getSplitOwner(TopicPartition tp, int numReaders) {
   
        int startIndex = ((tp.topic().hashCode() * 31) & 0x7FFFFFFF) % numReaders;

        // here, the assumption is that the id of Kafka partitions are always ascending
        // starting from 0, and therefore can be used directly as the offset clockwise from the
        // start index
        return (startIndex + tp.partition()) % numReaders;
    }

接着回答问题二,新的分区等 动态更新是从哪里来,从SourceCoordinator来,这才是大脑。当然也是需要work 做协同配合的工作。
从代码中就可以看出partitionDiscoveryIntervalMs,这个参数,就是如果其>0,那就定时和kafka 联系看看是否有新增partition 等。

 public void start() {
   
        consumer = getKafkaConsumer();
        adminClient = getKafkaAdminClient();
        if (partitionDiscoveryIntervalMs > 0) {
   
            LOG.info(
                    "Starting the KafkaSourceEnumerator for consumer group {} "
                            + "with partition discovery interval of {} ms.",
                    consumerGroupId,
                    partitionDiscoveryIntervalMs);
                    //关键在这里,如果partitionDiscoveryIntervalMs>0,这里就是一个定时服务了。
            context.callAsync(
            // 这里是发现多少个分区,并且进行划分
                    this::discoverAndInitializePartitionSplit,
                    // 这里就是要操作了
                    this::handlePartitionSplitChanges,
                    0,
                    partitionDiscoveryIntervalMs);
        } else {
   
            LOG.info(
                    "Starting the KafkaSourceEnumerator for consumer group {} "
                            + "without periodic partition discovery.",
                    consumerGroupId);
            context.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值