flink2_ source读取数据

本文详细介绍了 Apache Flink 中的数据源读取方法,包括从集合、文件及 Kafka 中读取数据的具体实现方式,并提供了自定义数据源的示例代码。

在flink程序流程中属于第二步

从集合或文件中读取

// 从集合中读取
env.fromCollection(Arrays.asList(
                "hello java",
                "hello spark",
                "hello flink",
                "hello scala"));

// 从文件中读取
env.readTextFile("<filePath>");

从kafka中读取

添加第三方包

<dependency>
    <groupId>org.apache.flink</groupId>
    <artifactId>flink-connector-kafka-0.11_2.11</artifactId>
    <version>1.10.1</version>
 </dependency>

连接代码

// 定义链接kafka的对应配置,告诉程序如何连接kafka,即kafka地址,offset的机制等
Properties properties = new Properties();
properties.setProperty("bootstrap.servers","localhost:9092");
properties.setProperty("group_id","consumer-group");
properties.setProperty("key.deserializer","org.apache.kafka.common.serialization.StrinDeserializer");       
properties.setProperty("value.deserializer","org.apache.kafka.common.serialization.StrinDeserializer");
properties.setProperty("auto.offset.reset","latest");

DataStreamSource<String> = 
          env.addSource(new FlinkKafkaConsumer010<String>(
                // kafka的topic
                "test",
                new SimpleStringSchema(),
                properties));

自定义source 数据源

package com.flinkTest.source;

import com.flinkTest.POJO.SensorReading;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.source.SourceFunction;

import java.util.HashMap;
import java.util.Random;

public class ModifyMySource {
    public static void main(String[] args) throws Exception {

        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        DataStreamSource inputStream = env.addSource(new MySource()); // 从自定义数据源读取数据

        inputStream.print(); // 没有逻辑处理,直接打印

        env.execute();

    }
    
    /** 自定义数据源, 数据是 生产1组 10个温度传感器的对象
     *  
     * */
    public static class  MySource<i> implements SourceFunction<SensorReading> {
        private boolean running = true;
        
        @Override
        public void run(SourceContext sourceContext) throws Exception {

            Random random = new Random();
            //生成10个初始sensor温度
            // 设置初始温度值(10个)
            HashMap<String,Double> tempMap = new HashMap<>();

            for (int i =0; i<10 ; i++){
                tempMap.put("sensor_" + (i+1), 60+random.nextGaussian()*20);
            }
            
            while(running){
                for(String id: tempMap.keySet()){
                    Double newTemp = tempMap.get(id) + random.nextGaussian();
                    tempMap.put(id,newTemp);
                    sourceContext.collect(new SensorReading(id,System.currentTimeMillis(),newTemp));
                }

                Thread.sleep(1000);
            }
        }

        @Override
        public void cancel() {
            running = false;
        }
    }
    
    // 温度传感器 内部类
    public  static  class SensorReading {
        private String id;
        private Long timestamp;
        private Double temperature;

    public SensorReading() {
        }

    public SensorReading(String id, Long timestamp, Double temperature) {
            this.id = id;
            this.timestamp = timestamp;
            this.temperature = temperature;
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public Long getTimestamp() {
            return timestamp;
        }

        public void setTimestamp(Long timestamp) {
            this.timestamp = timestamp;
        }

        public Double getTemperature() {
            return temperature;
        }

        public void setTemperature(Double temperature) {
            this.temperature = temperature;
        }

        @Override
        public String toString() {
            return "SensorReading{" +
                    "id='" + id + '\'' +
                    ", timestamp=" + timestamp +
                    ", temperature=" + temperature +
                    '}';
        }
    }
}

 

Flink SQL 中,从 Kafka Source 读取数据后进行 `rebalance` 操作,可以通过 SQL 语句中使用 `rebalance()` 函数来实现。这种操作主要用于重新分布数据流,以实现负载均衡和避免数据倾斜的问题。 ### 数据流重新平衡的实现方式 在 Flink SQL 中,可以使用 `rebalance()` 函数对 Kafka Source 的数据流进行重新分布。该操作会将数据随机分配到所有下游子任务中,从而打破数据分区的热点问题,使得任务处理更加均衡。例如: ```sql CREATE TABLE kafka_source ( ... ) WITH ( 'connector' = 'kafka', ... ); CREATE TABLE rebalanced_table AS SELECT * FROM kafka_source.rebalance(); ``` 上述 SQL 语句中,`rebalance()` 方法会将 Kafka Source 的数据流均匀地分发到后续操作的所有子任务中,从而实现数据流的重新平衡。 ### 使用场景 - **数据倾斜**:当某些分区的数据量远大于其他分区时,可以通过 `rebalance` 操作重新分布数据流,从而避免热点问题。 - **负载均衡**:在需要均匀分布数据流的情况下,例如处理高吞吐量的实时数据流时,可以使用 `rebalance` 来优化任务执行效率。 与 `keyBy` 相比,`rebalance` 不依赖于数据的键值,适用于需要避免数据倾斜的场景。而与 `broadcast` 相比,`rebalance` 并不会复制数据流,而是以随机方式将数据分布到所有子任务中,减少资源浪费。 ### 注意事项 - `rebalance` 操作会引入网络传输开销,因为它需要将数据从一个子任务传输到另一个子任务。 - 在某些情况下,如果数据流的分区已经均匀分布,则不需要进行 `rebalance` 操作,以避免不必要的性能损耗。 ### 示例代码 以下是一个完整的示例,展示如何在 Flink SQL 中使用 `rebalance`: ```sql -- 创建 Kafka Source 表 CREATE TABLE kafka_source ( id INT, name STRING, ts TIMESTAMP(3) ) WITH ( 'connector' = 'kafka', 'topic' = 'input-topic', 'properties.bootstrap.servers' = 'localhost:9092', 'format' = 'json' ); -- 创建 Rebalanced 表 CREATE TABLE rebalanced_table AS SELECT * FROM kafka_source.rebalance(); -- 查询 Rebalanced 表 SELECT * FROM rebalanced_table; ``` 在这个示例中,`kafka_source` 表的数据流通过 `rebalance()` 方法重新分布到 `rebalanced_table` 中,从而实现数据流的负载均衡。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值