Flink 源码解析(十)数据在各个task之间exchange的过程

数据流转过程
上一节讲了各层数据的抽象,这一节讲讲数据在各个task之间exchange的过程。

1 整体过程
看这张图:

在这里插入图片描述
第一步必然是准备一个ResultPartition;
通知JobMaster;
JobMaster通知下游节点;如果下游节点尚未部署,则部署之;
下游节点向上游请求数据
开始传输数据

.2 数据跨task传递
本节讲一下算子之间具体的数据传输过程。也先上一张图:
image_1cfmpba9v15anggtvsba2o1277m.png-357.5kB
数据在task之间传递有如下几步:

数据在本operator处理完后,交给RecordWriter。每条记录都要选择一个下游节点,所以要经过ChannelSelector。
每个channel都有一个serializer(我认为这应该是为了避免多线程写的麻烦),把这条Record序列化为ByteBuffer
接下来数据被写入ResultPartition下的各个subPartition里,此时该数据已经存入DirectBuffer(MemorySegment)
单独的线程控制数据的flush速度,一旦触发flush,则通过Netty的nio通道向对端写入
对端的netty client接收到数据,decode出来,把数据拷贝到buffer里,然后通知InputChannel
有可用的数据时,下游算子从阻塞醒来,从InputChannel取出buffer,再解序列化成record,交给算子执行用户代码
数据在不同机器的算子之间传递的步骤就是以上这些。

了解了步骤之后,再来看一下部分关键代码:
首先是把数据交给recordwriter。

//RecordWriterOutput.java
    @Override
    public void collect(StreamRecord<OUT> record) {
   
        if (this.outputTag != null) {
   
            // we are only responsible for emitting to the main input
            return;
        }
        //这里可以看到把记录交给了recordwriter
        pushToRecordWriter(record);
    }

然后recordwriter把数据发送到对应的通道。

//RecordWriter.java
    public void emit(T record) throws IOException, InterruptedException {
   
        //channelselector登场了
        for (int targetChannel : channelSelector.selectChannels(record, numChannels)) {
   
            sendToTarget(record, targetChannel);
        }
    }
    
        private void sendToTarget(T record, int targetChannel) throws IOException, InterruptedException {
   
        
        //选择序列化器并序列化数据
        RecordSerializer<T> serializer = serializers[targetChannel];

        SerializationResult result = serializer.addRecord(record);

        while (result.isFullBuffer()) {
   
            if (tryFinishCurrentBufferBuilder(targetChannel, serializer)) {
   
                // If this was a full record, we are done. Not breaking
                // out of the loop at this point will lead to another
                // buffer request before breaking out (that would not be
                // a problem per se, but it can lead to stalls in the
                // pipeline).
                if (result.isFullRecord()) {
   
                    break;
                }
            }
            BufferBuilder bufferBuilder = requestNewBufferBuilder(targetChannel);

            //写入channel
            result = serializer.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值