Apache Flink流分区器剖析

本文涉及的产品
实时计算 Flink 版,5000CU*H 3个月
简介: 这篇文章介绍Flink的分区器,在流进行转换操作后,Flink通过分区器来精确得控制数据流向。 StreamPartitioner StreamPartitioner是Flink流分区器的基类,它只定义了一个抽象方法: public abstract StreamPartition...

这篇文章介绍Flink的分区器,在流进行转换操作后,Flink通过分区器来精确得控制数据流向。

StreamPartitioner

StreamPartitioner是Flink流分区器的基类,它只定义了一个抽象方法:

    public abstract StreamPartitioner<T> copy();

但这个方法并不是各个分区器之间互相区别的地方,定义不同的分区器的核心在于——各个分区器需要实现channel选择的接口方法:

    int[] selectChannels(T record, int numChannels);

该方法针对当前的record以及所有的channel数目,返回一个针对当前这条记录采用的output channel的索引数组。(注意这里返回的是数组,说明一个记录可能会输出到多个channel这点我们后面会谈到)。

该接口方法来自于StreamPartitioner实现的接口ChannelSelector

分区器整体类图:

flink-data-stream-partitioner_class-diagram

GlobalPartitioner

全局分区器,其实现很简单——默认选择了索引为0的channel进行输出。

private int[] returnArray = new int[] { 0 };

@Override
public int[] selectChannels(SerializationDelegate<StreamRecord<T>> record,int numberOfOutputChannels) {
    return returnArray;
}

ForwardPartitioner

该分区器将记录转发给在本地运行的下游的(归属于subtask)的operattion。其实现跟上面的GlobalPartitioner一致,就不贴代码了。

ShufflePartitioner

混洗分区器,该分区器会在所有output channel中选择一个随机的进行输出。

private int[] returnArray = new int[1];

@Override
public int[] selectChannels(SerializationDelegate<StreamRecord<T>> record,int numberOfOutputChannels) {
    returnArray[0] = random.nextInt(numberOfOutputChannels);
    return returnArray;
}

HashPartitioner

hash分区器,该分区器对key进行hash后计算得到channel索引。它通过构造器获得KeySelector的实例(该实例用来获取当前记录的key)。

获得key后,通过其hashcodenumberOfOutputChannels取模后计算得出最终输出的channel的索引。

    public int[] selectChannels(SerializationDelegate<StreamRecord<T>> record,
            int numberOfOutputChannels) {
        Object key;
        try {
            key = keySelector.getKey(record.getInstance().getValue());
        } catch (Exception e) {
            throw new RuntimeException("Could not extract key from " + record.getInstance().getValue(), e);
        }
        returnArray[0] = MathUtils.murmurHash(key.hashCode()) % numberOfOutputChannels;

        return returnArray;
    }

BroadcastPartitioner

广播分区器,用于将该记录广播给下游的所有的subtask。这里采用了两个标记:

  • set
  • setNumber
    public int[] selectChannels(SerializationDelegate<StreamRecord<T>> record,
            int numberOfOutputChannels) {
        if (set && setNumber == numberOfOutputChannels) {
            return returnArray;
        } else {
            this.returnArray = new int[numberOfOutputChannels];
            for (int i = 0; i < numberOfOutputChannels; i++) {
                returnArray[i] = i;
            }
            set = true;
            setNumber = numberOfOutputChannels;
            return returnArray;
        }
    }

从上面的实现可见,它返回了一个跟numberOfOutputChannels相等的数组(数组的大小就是即将输出到channel的个数)。

RebalancePartitioner

重平衡分区器,用于实现类似于round-robin这样的轮转模式的分区器。通过累加、取模的形式来实现对输出channel的切换。

    public int[] selectChannels(SerializationDelegate<StreamRecord<T>> record,
            int numberOfOutputChannels) {
        this.returnArray[0] = (this.returnArray[0] + 1) % numberOfOutputChannels;
        return this.returnArray;
    }

RescalePartitioner

也是以round-robin的形式将元素分区到下游subtask的子集中。

上游操作所发送的元素被分区到下游操作的哪些子集,依赖于上游和下游操作的并行度。例如,如果上游操作的并行度为2,而下游操作的并行度为4,那么一个上游操作会分发元素给两个下游操作,同时另一个上游操作会分发给另两个下游操作。相反的,如果下游操作的并行度为2,而上游操作的并行度为4,那么两个上游操作会分发数据给一个下游操作,同时另两个上游操作会分发数据给另一个下游操作。

在上下游的并行度不是呈倍数关系的情况下,下游操作会有数量不同的来自上游操作的输入。具体的实现代码同RebalancePartitioner

CustomPartitionerWrapper

自定义分区器包装器,该包装器封装了对于自定义的分区器的实现。自定义的分区测量依赖于Partitioner接口。它提供了自定义分区器的契约。核心接口方法是:

    /**
     * Computes the partition for the given key.
     * 
     * @param key The key.
     * @param numPartitions The number of partitions to partition into.
     * @return The partition index.
     */
    int partition(K key, int numPartitions);

该接口方法的描述很清晰,通过给定的key以及numPartitions返回partition的index.

CustomPartitionerWrapper通过构造器注入Partitioner的实例,然后在selectChannels方法中通过partition接口来获得最终的channel索引。

    public int[] selectChannels(SerializationDelegate<StreamRecord<T>> record, int numberOfOutputChannels) {

        K key = null;
        try {
            key = keySelector.getKey(record.getInstance().getValue());
        } catch (Exception e) {
            throw new RuntimeException("Could not extract key from " + record.getInstance(), e);
        }

        returnArray[0] = partitioner.partition(key,
                numberOfOutputChannels);

        return returnArray;
    }

小结

以上的这些分区器,最终会体现在DataStream的API中用来对数据流进行物理分区。




原文发布时间为:2016-06-22


本文作者:vinoYang


本文来自云栖社区合作伙伴CSDN博客,了解相关信息可以关注CSDN博客。

相关实践学习
基于Hologres轻松玩转一站式实时仓库
本场景介绍如何利用阿里云MaxCompute、实时计算Flink和交互式分析服务Hologres开发离线、实时数据融合分析的数据大屏应用。
Linux入门到精通
本套课程是从入门开始的Linux学习课程,适合初学者阅读。由浅入深案例丰富,通俗易懂。主要涉及基础的系统操作以及工作中常用的各种服务软件的应用、部署和优化。即使是零基础的学员,只要能够坚持把所有章节都学完,也一定会受益匪浅。
目录
相关文章
|
1天前
|
Oracle 关系型数据库 数据库
实时计算 Flink版操作报错合集之执行Flink job,报错“Could not execute SQL statement. Reason:org.apache.flink.table.api.ValidationException: One or more required options are missing”,该怎么办
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
8 0
|
2天前
|
消息中间件 关系型数据库 MySQL
实时计算 Flink版操作报错合集之遇到报错:Apache Kafka Connect错误如何解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
13 5
|
2天前
|
SQL 关系型数据库 MySQL
实时计算 Flink版操作报错合集之报错:org.apache.flink.table.api.validationexception如何解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
9 1
|
2天前
|
存储 SQL 关系型数据库
实时计算 Flink版操作报错合集之报错:WARN (org.apache.kafka.clients.consumer.ConsumerConfig:logUnused)这个错误如何解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
13 3
|
3天前
|
SQL 消息中间件 Kafka
实时计算 Flink版产品使用合集之支持sink到多分区的kafka ,还能保持有序吗
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
18 0
|
5天前
|
消息中间件 API Apache
官宣|阿里巴巴捐赠的 Flink CDC 项目正式加入 Apache 基金会
本文整理自阿里云开源大数据平台徐榜江 (雪尽),关于阿里巴巴捐赠的 Flink CDC 项目正式加入 Apache 基金会。
1810 2
官宣|阿里巴巴捐赠的 Flink CDC 项目正式加入 Apache 基金会
|
5天前
|
消息中间件 Kafka Apache
Apache Flink 是一个开源的分布式流处理框架
Apache Flink 是一个开源的分布式流处理框架
722 5
|
5天前
|
SQL Java API
官宣|Apache Flink 1.19 发布公告
Apache Flink PMC(项目管理委员)很高兴地宣布发布 Apache Flink 1.19.0。
1797 2
官宣|Apache Flink 1.19 发布公告
|
5天前
|
SQL Apache 流计算
Apache Flink官方网站提供了关于如何使用Docker进行Flink CDC测试的文档
【2月更文挑战第25天】Apache Flink官方网站提供了关于如何使用Docker进行Flink CDC测试的文档
349 3
|
5天前
|
Oracle 关系型数据库 流计算
flink cdc 同步问题之报错org.apache.flink.util.SerializedThrowable:如何解决
Flink CDC(Change Data Capture)是一个基于Apache Flink的实时数据变更捕获库,用于实现数据库的实时同步和变更流的处理;在本汇总中,我们组织了关于Flink CDC产品在实践中用户经常提出的问题及其解答,目的是辅助用户更好地理解和应用这一技术,优化实时数据处理流程。
439 0

热门文章

最新文章

推荐镜像

更多