第三篇|Flink DataStream API编程指南

Flink DataStream API使用及原理 flink DataStream API使用及原理 传统的大数据处理方式一般是批处理式的,也就是说,今天所收集的数据,我们明天再把今天收集到的数据算出来,以供大家使用,但是在很多情况下,数据的时效性对于业务的成败是非常关键的。 Spark 和 Flink 都是通用的开源大规模处理引擎,目标是在一个系统中支持所有的数据处理以带来效能的提升。两者都有相对比较成熟的生态系统。是下一代大数据... 阅读详情

Flink DataStream API主要分为三个部分,分别为Source、Transformation以及Sink,其中Source是数据源,Flink内置了很多数据源,比如最常用的Kafka。Transformation是具体的转换操作,主要是用户定义的处理数据的逻辑,比如Map,FlatMap等。Sink(数据汇)是数据的输出,可以把处理之后的数据输出到存储设备上,Flink内置了许多的Sink,比如Kafka,HDFS等。另外除了Flink内置的Source和Sink外,用户可以实现自定义的Source与Sink。考虑到内置的Source与Sink使用起来比较简单且方便,所以,关于内置的Source与Sink的使用方式不在本文的讨论范围之内,本文会先从自定义Source开始说起,然后详细描述一些常见算子的使用方式,最后会实现一个自定义的Sink。

数据源

Flink内部实现了比较常用的数据源,比如基于文件的,基于Socket的,基于集合的等等,如果这些都不能满足需求,用户可以自定义数据源,下面将会以MySQL为例,实现一个自定义的数据源。本文的所有操作将使用该数据源,具体代码如下:

/**
 *  @Created with IntelliJ IDEA.
 *  @author : jmx
 *  @Date: 2020/4/14
 *  @Time: 17:34
 * note: RichParallelSourceFunction与SourceContext必须加泛型
 */
public class MysqlSource extends RichParallelSourceFunction<UserBehavior> {
    public Connection conn;
    public PreparedStatement pps;
    private String driver;
    private String url;
    private String user;
    private String pass;

    /**
     * 该方法只会在最开始的时候被调用一次
     * 此方法用于实现获取连接
     *
     * @param parameters
     * @throws Exception
     */
    @Override
    public void open(Configuration parameters) throws Exception {
        //初始化数据库连接参数
        Properties properties = new Properties();
        URL fileUrl = TestProperties.class.getClassLoader().getResource("mysql.ini");
        FileInputStream inputStream = new FileInputStream(new File(fileUrl.toURI()));
        properties.load(inputStream);
        inputStream.close();
        driver = properties.getProperty("driver");
        url = properties.getProperty("url");
        user = properties.getProperty("user");
        pass = properties.getProperty("pass");
        //获取数据连接
        conn = getConection();
        String scanSQL = "SELECT * FROM user_behavior_log";
        pps = conn.prepareStatement(scanSQL);
    }

    @Override
    public void run(SourceContext<UserBehavior> ctx) throws Exception {
        ResultSet resultSet = pps.executeQuery();
        while (resultSet.next()) {
            ctx.collect(UserBehavior.of(
                    resultSet.getLong("user_id"),
                    resultSet.getLong("item_id"),
                    resultSet.getInt("cat_id"),
                    resultSet.getInt("merchant_id"),
                    resultSet.getInt("brand_id"),
                    resultSet.getString("action"),
                    resultSet.getString("gender"),
                    resultSet.getLong("timestamp")));
        }
    }
    @Override
    public void cancel() {

    }
    /**
     * 实现关闭连接
     */
    @Override
    public void close() {
        if (pps != null) {
            try {
                pps.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 获取数据库连接
     *
     * @return
     * @throws SQLException
     */
    public Connection getConection() throws IOException {
        Connection connnection = null;

        try {
            //加载驱动
            Class.forName(driver);
            //获取连接
            connnection = DriverManager.getConnection(
                    url,
                    user,
                    pass);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return connnection;

    }
}
复制代码

首先继承RichParallelSourceFunction,实现继承的方法,主要包括open()方法、run()方法及close方法。上述的

RichParallelSourceFunction是支持设置多并行度的,关于RichParallelSourceFunction与RichSourceFunction的区别,前者支持用户设置多并行度,后者不支持通过setParallelism()方法设置并行度,默认的并行度为1,否则会报如下错误:bashException in thread "main" java.lang.IllegalArgumentException: The maximum parallelism of non parallel operator must be 1.

另外,RichParallelSourceFunction提供了额外的open()方法与close()方法,如果定义Source时需要获取链接,那么可以在open()方法中进行初始化,然后在close()方法中关闭资源链接,关于Rich***Function与普通Function的区别,下文会详细解释,在这里先有个印象。上述的代码中的配置信息是通过配置文件传递的,由于篇幅限制,我会把本文的代码放置在github,见文末github地址。

基本转换

Flink提供了大量的算子操作供用户使用,常见的算子主要包括以下几种,注意:本文不讨论关于基于时间与窗口的算子,这些内容会在《Flink基于时间与窗口的算子》中进行详细介绍。

说明:本文的操作是基于上文自定义的MySQL Source,对应的数据解释如下:

userId;     // 用户ID
itemId;     // 商品ID
catId;      // 商品类目ID
merchantId; // 卖家ID
brandId;    // 品牌ID
action;     // 用户行为, 包括("pv", "buy", "cart", "fav")
gender;     // 性别
timestamp;  // 行为发生的时间戳,单位秒
复制代码

Map

解释

DataStream → DataStream 的转换,输入一个元素,返回一个元素,如下操作:

SingleOutputStreamOperator<String> userBehaviorMap = userBehavior.map(new RichMapFunction<UserBehavior, String>() {
            @Override
            public String map(UserBehavior value) throws Exception {
                String action = "";
                switch (value.action) {
                    case "pv":
                        action = "浏览";
                    case "cart":
                        action = "加购";
                    case "fav":
                        action = "收藏";
                    case "buy":
                        action = "购买";
                }
                return action;
            }
        });
复制代码

示意图

将雨滴形状转换成相对应的圆形形状的map操作

flatMap

解释

DataStream → DataStream,输入一个元素,返回零个、一个或多个元素。事实上,flatMap算子可以看做是filter与map的泛化,即它能够实现这两种操作。flatMap算子对应的FlatMapFunction定义了flatMap方法,可以通过向collector对象传递数据的方式返回0个,1个或者多个事件作为结果。如下操作:

SingleOutputStreamOperator<UserBehavior> userBehaviorflatMap = userBehavior.flatMap(new RichFlatMapFunction<UserBehavior, UserBehavior>() {
            @Override
            public void flatMap(UserBehavior value, Collector<UserBehavior> out) throws Exception {
                if (value.gender.equals("女")) {
                    out.collect(value);
                }
            }
        });
复制代码

示意图

将黄色的雨滴过滤掉,将蓝色雨滴转为圆形,保留绿色雨滴

Filter

解释

DataStream → DataStream,过滤算子,对数据进行判断,符合条件即返回true的数据会被保留,否则被过滤。如下:

  SingleOutputStreamOperator<UserBehavior> userBehaviorFilter = userBehavior.filter(new RichFilterFunction<UserBehavior>() {
            @Override
            public boolean filter(UserBehavior value) throws Exception {
                return value.action.equals("buy");//保留购买行为的数据
            }
        });
复制代码

示意图

将红色与绿色雨滴过滤掉,保留蓝色雨滴。

keyBy

解释

DataStream→KeyedStream,从逻辑上将流划分为不相交的分区。具有相同键的所有记录都分配给同一分区。在内部,keyBy()是通过哈希分区实现的。 定义键值有3中方式: (1)使用字段位置,如keyBy(1),此方式是针对元组数据类型,比如tuple,使用元组相应元素的位置来定义键值; (2)字段表达式,用于元组、POJO以及样例类; (3)键值选择器,即keySelector,可以从输入事件中提取键值

SingleOutputStreamOperator<Tuple2<String, Integer>> userBehaviorkeyBy = userBehavior.map(new RichMapFunction<UserBehavior, Tuple2<String, Integer>>() {
            @Override
            public Tuple2<String, Integer> map(UserBehavior value) throws Exception {
                return Tuple2.of(value.action.toString(), 1);
            }
        }).keyBy(0) // scala元组编号从1开始,java元组编号是从0开始
           .sum(1); //滚动聚合
复制代码

示意图

基于形状对事件进行分区的keyBy操作

Reduce

解释

KeyedStream → DataStream,对数据进行滚动聚合操作,结合当前元素和上一次Reduce返回的值进行聚合,然后返回一个新的值.将一个ReduceFunction应用在一个keyedStream上,每到来一个事件都会与当前reduce的结果进行聚合, 产生一个新的DataStream,该算子不会改变数据类型,因此输入流与输出流的类型永远保持一致。

SingleOutputStreamOperator<Tuple2<String, Integer>> userBehaviorReduce = userBehavior.map(new RichMapFunction<UserBehavior, Tuple2<String, Integer>>() {
            @Override
            public Tuple2<String, Integer> map(UserBehavior value) throws Exception {
                return Tuple2.of(value.action.toString(), 1);
            }
        }).keyBy(0) // scala元组编号从1开始,java元组编号是从0开始
          .reduce(new RichReduceFunction<Tuple2<String, Integer>>() {
              @Override
              public Tuple2<String, Integer> reduce(Tuple2<String, Integer> value1, Tuple2<String, Integer> value2) throws Exception {
                  return Tuple2.of(value1.f0,value1.f1 + value2.f1);//滚动聚合,功能与sum类似
              }
          });
复制代码

示意图

Aggregations(滚动聚合)

KeyedStream → DataStream,Aggregations(滚动聚合),滚动聚合转换作用于KeyedStream流上,生成一个包含聚合结果(比如sum求和,min最小值)的DataStream,滚动聚合的转换会为每个流过该算子的key值保存一个聚合结果, 当有新的元素流过该算子时,会根据之前的结果值和当前的元素值,更新相应的结果值

  • sum():滚动聚合流过该算子的指定字段的和;
  • min():滚动计算流过该算子的指定字段的最小值
  • max():滚动计算流过该算子的指定字段的最大值
  • minBy():滚动计算当目前为止流过该算子的最小值,返回该值对应的事件;
  • maxBy():滚动计算当目前为止流过该算子的最大值,返回该值对应的事件;

union

解释

DataStream* → DataStream,将多条流合并,新的的流会包括所有流的数据,值得注意的是,两个流的数据类型必须一致,另外,来自两条流的事件会以FIFO(先进先出)的方式合并,所以并不能保证两条流的顺序,此外,union算子不会对数据去重,每个输入事件都会被发送到下游算子。

userBehaviorkeyBy.union(userBehaviorReduce).print();//将两条流union在一起,可以支持多条流(大于2)的union
复制代码

示意图

connect

解释

DataStream,DataStream → ConnectedStreams,将两个流的事件进行组合,返回一个ConnectedStreams对象,两个流的数据类型可以不一致,ConnectedStreams对象提供了类似于map(),flatMap()功能的算子,如CoMapFunction与CoFlatMapFunction分别表示map()与flatMap算子,这两个算子会分别作用于两条流,注意:CoMapFunction 或CoFlatMapFunction被调用的时候并不能控制事件的顺序只要有事件流过该算子,该算子就会被调用。

ConnectedStreams<UserBehavior, Tuple2<String, Integer>> behaviorConnectedStreams = userBehaviorFilter.connect(userBehaviorkeyBy);
        SingleOutputStreamOperator<Tuple3<String, String, Integer>> behaviorConnectedStreamsmap = behaviorConnectedStreams.map(new RichCoMapFunction<UserBehavior, Tuple2<String, Integer>, Tuple3<String, String, Integer>>() {
            @Override
            public Tuple3<String, String, Integer> map1(UserBehavior value1) throws Exception {
                return Tuple3.of("first", value1.action, 1);
            }
            @Override
            public Tuple3<String, String, Integer> map2(Tuple2<String, Integer> value2) throws Exception {
                return Tuple3.of("second", value2.f0, value2.f1);
            }
        });
复制代码

split

解释

DataStream → SplitStream,将流分割成两条或多条流,与union相反。分割之后的流与输入流的数据类型一致, 对于每个到来的事件可以被路由到0个、1个或多个输出流中。可以实现过滤与复制事件的功能,DataStream.split()接收一个OutputSelector函数,用来定义分流的规则,即将满足不同条件的流分配到用户命名的一个输出。

 SplitStream<UserBehavior> userBehaviorSplitStream = userBehavior.split(new OutputSelector<UserBehavior>() {
            @Override
            public Iterable<String> select(UserBehavior value) {
                ArrayList<String> userBehaviors = new ArrayList<String>();
                if (value.action.equals("buy")) {
                    userBehaviors.add("buy");
                } else {
                    userBehaviors.add("other");
                }
                return userBehaviors;
            }
        });
userBehaviorSplitStream.select("buy").print();
复制代码

示意图

Sink

Flink提供了许多内置的Sink,比如writeASText,print,HDFS,Kaka等等,下面将基于MySQL实现一个自定义的Sink,可以与自定义的MysqlSource进行对比,具体如下:

/**
 *  @Created with IntelliJ IDEA.
 *  @author : jmx
 *  @Date: 2020/4/16
 *  @Time: 22:53
 *  
 */
public class MysqlSink extends RichSinkFunction<UserBehavior> {
    PreparedStatement pps;
    public Connection conn;
    private String driver;
    private String url;
    private String user;
    private String pass;
    /**
     * 在open() 方法初始化连接
     *
     * @param parameters
     * @throws Exception
     */
    @Override
    public void open(Configuration parameters) throws Exception {
        //初始化数据库连接参数
        Properties properties = new Properties();
        URL fileUrl = TestProperties.class.getClassLoader().getResource("mysql.ini");
        FileInputStream inputStream = new FileInputStream(new File(fileUrl.toURI()));
        properties.load(inputStream);
        inputStream.close();
        driver = properties.getProperty("driver");
        url = properties.getProperty("url");
        user = properties.getProperty("user");
        pass = properties.getProperty("pass");
        //获取数据连接
        conn = getConnection();
        String insertSql = "insert into user_behavior values(?, ?, ?, ?,?, ?, ?, ?);";
        pps = conn.prepareStatement(insertSql);
    }

    /**
     * 实现关闭连接
     */
    @Override
    public void close() {

        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (pps != null) {
            try {
                pps.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 调用invoke() 方法,进行数据插入
     *
     * @param value
     * @param context
     * @throws Exception
     */
    @Override
    public void invoke(UserBehavior value, Context context) throws Exception {
        pps.setLong(1, value.userId);
        pps.setLong(2, value.itemId);
        pps.setInt(3, value.catId);
        pps.setInt(4, value.merchantId);
        pps.setInt(5, value.brandId);
        pps.setString(6, value.action);
        pps.setString(7, value.gender);
        pps.setLong(8, value.timestamp);
        pps.executeUpdate();
    }
    /**
     * 获取数据库连接
     *
     * @return
     * @throws SQLException
     */
    public Connection getConnection() throws IOException {
        Connection connnection = null;

        try {
            //加载驱动
            Class.forName(driver);
            //获取连接
            connnection = DriverManager.getConnection(
                    url,
                    user,
                    pass);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return connnection;
    }
}
复制代码

关于RichFunction

细心的读者可以发现,在前文的算子操作案例中,使用的都是RichFunction,因为在很多时候需要在函数处理数据之前先进行一些初始化操作,或者获取函数的上下文信息,DataStream API提供了一类RichFunction,与普通的函数相比,该函数提供了许多额外的功能。

使用RichFunction的时候,可以实现两个额外的方法:

  • open(),是初始化方法,会在每个人物首次调用转换方法(比如map)前调用一次。通常用于进行一次的设置工作,注意Configuration参数只在DataSet API中使用,而并没有在DataStream API中使用,因此在使用DataStream API时,可以将其忽略。
  • close(),函数的终止方法 ,会在每个任务最后一次调用转换方法后调用一次,通常用于资源释放等操作。

此外用户还可以通过getRuntimeContext()方法访问函数的上下文信息(RuntimeContext),例如函数的并行度,函数所在subtask的编号以及执行函数的任务名称,同时也可以访问分区状态。

总结

本文首先实现了自定义MySQL Source,然后基于MySql 的Source进行了一系列的算子操作,并对常见的算子操作进行详细剖析,最后实现了一个自定义MySQL Sink,并对RichFunction进行了解释。

代码地址:github.com/jiamx/study…

作者:大数据技术与数仓
链接:https://juejin.cn/post/6857499033612845063
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Flink的RichParallelSourceFunction详解 它是ParallelSourceFunction的子类,相比于ParallelSourceFunction,RichParallelSourceFunction提供了更多的生命周期方法和上下文信息。通过继承该类并实现相应的方法,我们可以定义自己的并行数据源,并在Flink应用程序中使用它。通过上述示例,我们可以看到如何使用RichParallelSourceFunction来定义自定义的并行数据源,并在Flink应用程序中使用它。在上面的示例中,我们首先定义了一个自定义的并行数据源。将数据发送给下游算子。 阅读详情

相关推荐

Flink DataStream 富函数 RichFunction

很多时候,我们需要在函数处理第一条记录之前进行一些初始化的工作或者获得函数执行上下文的一些信息,以及在处理完记录后做一些清理工作。而 DataStream API 中的富函数 RichFunction 就提供了这样的机制。DataStream API 提供了一类富函数,和普通函数相比可对外提供跟多的功能。

SmartSi 967

聊聊flink的RichParallelSourceFunction

序 本文主要研究一下flink的RichParallelSourceFunction RichParallelSourceFunction /** * Base class for implementing a parallel data source. Upon execution, the runtime will * execu...

weixin_34318272的博客 1368

Flink原理与实战(java版)#第6章 Flink的 DataStream API(第一节DataStream API 编程指南(一))

第一节介绍了Flink DataStream API编程指南,该部分是使用Flink的基础。通过DataStream API程序剖析、DataSource、Transformation、Sink、Iteration、执行参数和调试几个角度进行介绍,并以一个示例展示其常见的使用方式。在完成本节的学习后,基本上能熟练的使用DataStream API,不同的是在该节的基础上了解更多的API的使用方式。

alanchanchn的专栏 1万+

Flink算子之RichParallelSourceFunction、RichSourceFunction因数据源不同,存在的差异

两套代码流程,完全一样。但是在读取到同样的数据后,数据返回给addSource算子后,通过transform算子后,继承RichSourceFunction的消息会出现丢失。 但是是区分数据源的,MySQL就没有类似的情况,但是Elasticsearch就会出现。 public class ElasticSource extends RichParallelSourceFunction<String>/RichSourceFunction { @Override pub.

为一个人走几座城 2967

手把手教你使用ESM-2进行蛋白质结构预测:从安装到实战

本文详细介绍了如何使用ESM-2蛋白质语言模型进行蛋白质结构预测,从环境准备、模型安装到实战应用。通过逐步指导,读者可以掌握ESM-2的配置、单序列预测、结果可视化及高级优化技巧,适用于生物信息学研究和药物开发。

weixin_29306875的博客 532

小蔺的米哈游数据分析师之路——MYSQL篇

作为新人,记录自己mysql学习历程

weixin_47070228的博客 433

Flink1.12 -- 流批一体API

1. 流处理相关概念 1.1 数据的时效性  日常工作中,我们一般会先把数据存储在表,然后对表的数据进行加工、分析。既然先存储在表中,那就会涉及到时效性概念。  如果我们处理以年,月为单位的级别的数据处理,进行统计分析,个性化推荐,那么数据的的最新日期离当前有几个甚至上月都没有问题。但是如果我们处理的是以天为级别,或者一小时甚至更小粒度的数据处理,那么就要求数据的时效性更高了。比如:对网站的实时监控、对异常日志的监控,这些场景需要工作人员立即响应,这样的场景下,传统的统一收集数据,再存到数据库中,再取出

erainm 1488

影刀RPA验证码识别避坑指南:官方指令、Python ddddocr与第三方图鉴怎么选?

本文深度对比了影刀RPA验证码识别的三种方案:官方AI指令、Python ddddocr开源库和第三方图鉴服务。从识别率、成本、维护性等维度分析各方案优劣,提供实战选型建议和优化技巧,帮助技术决策者在自动化流程中高效解决验证码识别难题。

weixin_30790841的博客 471

48、Flink DataStream API 编程指南- 完整版

addSource - 关联一个新的 source function。例如,你可以使用 addSource(new FlinkKafkaConsumer(…)) 来从 Apache Kafka 获取数据。其中的maven依赖参考本专栏的相关文章kafka该示例是基于flink1.13.5的版本/**/**// source // 准备kafka连接参数 Properties props = new Properties();

alanchanchn的专栏 6万+

算法基础之数组双指针(Leetcode题型归纳)

数组双指针(Leetcode题型归纳)1.前言2.双指针基础3.相向双指针3.1定义3.2真题分析3.2.1两数之和(1)3.2.2两数之和-输入有序数组(167)3.2.3三数之和(15)3.2.4最接近的三数之和(16)3.2.5四数之和(18)3.2.6盛最多水的容器(11)3.2.7有效三角形的个数(611)4.同向双指针-快慢指针4.1定义4.2真题分析4.1.1删除排序数组中的重复项(26)4.1.2移除元素(27)4.1.3删除排序数组中的重复项(80)4.1.4移动零(283)4.1.5数组

Buluchacha的博客 1034

MATLAB 论文复现——含氢综合能源系统多目标最优折中分布鲁棒低碳调度

提出基于多目标决策理论和逼近理想解排序技术,构造综合考虑系统调度的经济性、低碳性和鲁棒度的多目标最优折中函数,从而建立含氢综合能源系统多目标最优折中分布鲁棒低碳调度模型,可快速准确地获得兼具经济性、低碳性和鲁棒性的含氢综合能源系统优化调度方案。[1]孙惠娟,胡紫平,彭春华,等.含氢综合能源系统多目标最优折中分布鲁棒低碳调度[J/OL].电力自动化设备,1-13[2024-07-26].https://doi.org/10.16081/j.epae.202406003.关键词: 综合能源系统;

sjr1478的博客 410

48、Flink DataStream API 编程指南(1)- DataStream 入门示例

通常,只需要使用 getExecutionEnvironment() 即可,因为该方法会根据上下文做正确的处理:如果你在 IDE 中执行你的程序或将其作为一般的 Java 程序执行,那么它将创建一个本地环境,该环境将在你的本地机器上执行你的程序。如果你基于程序创建了一个 JAR 文件,并通过命令行运行它,Flink 集群管理器将执行程序的 main 方法,同时 getExecutionEnvironment() 方法会返回一个执行环境以在集群上执行你的程序。

alanchanchn的专栏 6万+

【向量数据库】Milvus向量数据库 ① 从入门到实战

Milvus是专为海量高维向量设计的开源数据库,支持AI搜索、图像识别、推荐系统等场景。相比传统关系型数据库(如PostgreSQL),它更高效处理语义检索、非结构化数据存储,可毫秒级响应亿级向量查询。单机场景下,推荐配置8GB内存/32GB硬盘,支持FAISS/HNSW等索引算法,支持GPU加速。本文涵盖优快云专属部署教程(CentOS脚本/配置调优),提供避坑指南与扩展资源,并对比分析与传统数据库差异。适合算法工程师、AI开发人员快速上手,附官方下载与性能测试技巧,手把手教你搭建高效向量检索系统!

xiezhiyi007的专栏 1586

48、Flink DataStream API 编程指南(2)- DataStream的source、transformation、sink、调试

addSource - 关联一个新的 source function。例如,你可以使用 addSource(new FlinkKafkaConsumer(…)) 来从 Apache Kafka 获取数据。其中的maven依赖参考本专栏的相关文章kafka该示例是基于flink1.13.5的版本/**/**// source // 准备kafka连接参数 Properties props = new Properties();

alanchanchn的专栏 6万+

飞塔CVE-2022-40684复现

admin 无密码直接回车(会提示修改密码)

G3et的博客 1145

Python爬虫:爬取拼多多平台商品信息、销量、价格等数据

在本篇博客中,我们将深入探讨如何使用Python爬虫技术爬取拼多多平台的商品信息,包括商品的标题、销量、价格等详细数据。拼多多的商品页面通常是分页展示的,因此我们需要遍历多个页面,获取所有商品的信息。每个商品在拼多多平台上都有一个唯一的商品ID,我们可以通过该ID访问商品页面。通过以上的技术方案和代码示例,你已经掌握了如何使用Python爬虫获取拼多多平台上的商品信息、销量、价格等数据。等技术,解决拼多多平台的反爬虫机制,成功抓取我们所需的商品数据。,我们能够应对拼多多的反爬虫机制,稳定地获取到商品数据。

2201_76125261的博客 3655

【Flink系列】5. DataStream API

5. DataStream API DataStream API是Flink的核心层API。一个Flink程序,其实就是对DataStream的各种转换。具体来说,代码基本上都由以下几部分构成: 5.1 执行环境(Execution Environment) Flink程序可以在各种上下文环境中运行:我们可以在本地JVM中执行程序,也可以提交到远程集群上运行。 不同的环境,代码的提交运行的过程会有所不同。这就要求我们在提交作业执行计算时,首先必须获取当前Flink的运行环境,从而建立起与Flink框架之间

ayt007的博客 1272

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Flink DataStream API

Flink DataStream API 编程指南概览前言什么是DataStreamFlink程序剖析程序样例Data SourcesDataStream Transformations算子数据流转换算子物理分区算子链和资源组Data Sinks迭代执行参数 概览 前言 Flink中的DataStream程序是常规程序,可对数据流进行转换(例如,过滤,更新状态,定义窗口,聚合)。数据流最初是从各种来源(例如消息队列,套接字流,文件)创建的。结果通过接收器返回,接收器可以例如将数据写入文件或标准输出(例如命令

17611119847 4万+

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Flink DataStream API 编程指南

  原文链接:https://ci.apache.org/projects/flink/flink-docs-release-1.3/dev/datastream_api.html Flink中的DataStream程序是在数据流中实现transformation操作(如:过滤、修改状态、定义窗口、聚合等)的常规程序。数据流通过各种source(如: 消息队列、socket流、文件等)来创建,结...

resemble的博客 1291

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Flink 编程基础:Scala 版 DataStream API 入门

流处理技术在大数据时代正变得越来越重要,而 Apache Flink 作为领先的流处理引擎,凭借其高性能、低延迟和丰富的 API 受到了广泛关注。本文将以 Scala 语言为例,详细讲解 Flink DataStream API 的基本编程模型,从数据源、数据转换、数据输出,到窗口划分与时间概念,最后结合经典的 WordCount 案例,带大家一步步动手实践。

weixin_66485800的博客 1534

【Flink】Flink编程模型:DataStream与DataSet

这篇文章我们来聊聊 Flink 的编程模型,搞清楚 DataStream、DataSet 这些 API 到底是什么关系,以及 Flink 1.12 之后的"流批一体"是怎么回事。

weixin_63434398的博客 978

flink-java使用介绍,flink,java,DataStream API,DataSet API,ETL,设置 jobname

flink-java使用介绍,flink,java,DataStream API,DataSet API,ETL

猛犸象 2341

Flink架构概览,Flink DataStream API 的使用,FlinkCDC的使用

Flink是一个高性能的分布式流处理引擎,支持精确一次(Exactly-Once)语义,广泛应用于大数据实时处理场景。其核心架构包括Client、JobManager、TaskManager和Slot,分别负责作业提交、调度、任务执行和资源管理。Flink与Hadoop生态系统深度集成,能够与HDFS、Hive、Kafka、HBase、YARN和Zookeeper等组件协同工作,构建完整的大数据处理链路。例如,Flink可以直接读取HDFS中的数据,将计算结果写入Hive表,或通过Kafka进行实时数据采集

lrj41781196的博客 2543
上一篇: 第四篇|Flink DataStream API 中的多面手——Process Function详解
下一篇: 第二篇|Flink DataSet API编程指南
wrr-cat
博客等级 码龄9年 128粉丝 302原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值