SparkStreaming(七)操作函数之Join Operations、Output Operations

目录:

5.3 Join Operations

5.3.1、DStream对象之间的Join

5.3.2、DStream和dataset之间的join

5.4、Output Operations

5.4.1、print()

5.4.2、saveAsTextFiles(prefix, [suffix])

5.4.3、saveAsObjectFiles(prefix, [suffix])

5.4.4、saveAsHadoopFiles(prefix, [suffix])

5.4.5、foreachRDD(func)


5.3 Join Operations

Join主要可分为两种。

5.3.1、DStream对象之间的Join

         这种join一般应用于窗口函数形成的DStream对象之间,具体可以参考第一部分中的join操作,除了简单的join之外,还有leftOuterJoin, rightOuterJoin和fullOuterJoin。

5.3.2、DStream和dataset之间的join

这一种join,可以参考前面transform操作中的示例。

5.4、Output Operations

在Spark Streaming中,DStream的输出操作才是DStream上所有transformations的真正触发计算点,这个类似于RDD中的action操作。经过输出操作DStream中的数据才能与外部进行交互,比如将数据写入文件系统、数据库,或其他应用中。 

Output Operation

Meaning

print()

在运行streaming应用程序的driver节点上打印DStream中每个batch的前十个元素。一般用于开发和调试。

saveAsTextFiles(prefix, [suffix])

将此DStream的内容保存到文本文件中。每个批数据对应的文件名基于prefix和suffix生成:“prefix-TIME_IN_MS [.suffix]”。

saveAsObjectFiles(prefix, [suffix])

将此DStream的内容另存为SequenceFiles格式的序列化Java对象。 每个批数据对应的文件名基于prefix和suffix生成“prefix-TIME_IN_MS [.suffix]”。

saveAsHadoopFiles(prefix, [suffix])

将此DStream的内容另存为Hadoop文件。 每个批数据对应的文件名基于prefix和suffix生成“prefix-TIME_IN_MS [.suffix]”。

foreachRDD(func)

这是流数据处理中最常用的输出操作,它可以对数据流中的每个RDD应用func方法。此方法应将每个RDD中的数据推送到外部系统,例如将RDD保存到文件,或将其通过网络写入数据库。请注意,函数func在运行streaming应用程序的driver进程中执行,通常会包括RDD action算子,从而强制流式RDD数据的计算执行。

5.4.1、print()

print操作会将DStream每一个batch中的前10个元素在driver节点打印出来。

  看下面这个示例,一行输入超过10个单词,然后将这行语句分割成单个单词的DStream。

服务端:

客户端:

结果:

5.4.2、saveAsTextFiles(prefix, [suffix])

这个操作可以将DStream中的内容保存为text文件,每个batch的数据单独保存为一个文夹,文件夹名前缀参数必须传入,文件夹名后缀参数可选,最终文件夹名称的完整形式为prefix-TIME_IN_MS[.suffix]

比如下面这一行代码:

dStream.saveAsTextFiles("E:\\spark\\saveAsTextFile\\satf", "txt");

服务端:

客户端:

5.4.3、saveAsObjectFiles(prefix, [suffix])

这个操作和前面一个类似,只不过这里将此Dstream的内容保存为序列化的java 对象SequenceFiles。每批次数据产生的文件名称格式基于:prefix和suffix: "prefix-TIME_IN_MS[.suffix]"

注意:

spark中普通rdd可以只用saveAsTextFile(path)的方式,保存到本地,但是此时DStream的只有saveAsTextFiles()方法,没有传入路径的方法,其参数只有prefix, suffix。

其实DStream中的saveAsTextFiles方法中又调用了rdd中的saveAsTextFile方法,我们需要将path包含在prefix中。

实验略过,可参考前面一个操作。

dStream.saveAsObjectFiles("E:\\spark\\saveAsObjectFiles\\prefix", "suffix");

5.4.4、saveAsHadoopFiles(prefix, [suffix])

这个操作和前两个类似,将此DStream的内容另存为Hadoop文件。每批次数据产生的文件名称格式基于:prefix和suffix:”prefix-TIME_IN_MS[.suffix”

示例:

5.4.5、foreachRDD(func)

foreachRDD是一个功能强大的原语,它允许将数据发送到外部系统。通常向外部系统写入数据需要创建一个连接对象(例如到远程服务器的TCP连接)并使用它向远程系统发送数据。为此,开发人员可在Spark驱动程序上创建连接对象,然后尝试在Spark worker中使用它来保存RDDs中的记录。

dstream.foreachRDD(rdd -> {
  Connection connection = createNewConnection(); // 在driver上执行
  rdd.foreach(record -> {
    connection.send(record); // 在worker上执行
  });
}); 

这是不正确的,因为这要求连接对象被序列化并从驱动程序发送到工作程序。这样的连接对象很少可以跨机器进行传输。这个错误可以表现为序列化错误(连接对象不可序列化)、初始化错误(连接对象需要在worker上初始化)等。正确的解决方案是在worker上创建连接对象。

然而,这可能导致另一个常见错误——为每条记录创建一个新的连接。例如:

dstream.foreachRDD(rdd -> {
  rdd.foreach(record -> {
    Connection connection = createNewConnection();
    connection.send(record);
    connection.close();
  });
});

通常,创建连接对象需要花费时间和资源。因此,为每个记录创建和销毁连接对象可能会导致不必要的高开销,并会显著降低系统的总体吞吐量。更好的解决方案是使用rddforeachPartition——创建一个连接对象,并使用该连接发送RDD分区中的所有记录。

dstream.foreachRDD(rdd -> {
  rdd.foreachPartition(partitionOfRecords -> {
    Connection connection = createNewConnection();
    while (partitionOfRecords.hasNext()) {
      connection.send(partitionOfRecords.next());
    }
    connection.close();
  });
});

这将使连接创建的开销分散到许多记录上。

最后,可以通过跨多个RDDs/batch重用连接对象进一步优化。可以维护一个连接对象的静态池,当多个批次的RDDs被推到外部系统时可以重用,从而进一步减少开销。

dstream.foreachRDD(rdd -> {
  rdd.foreachPartition(partitionOfRecords -> {
    // ConnectionPool是一个静态的、惰性初始化的连接池 
    Connection connection = ConnectionPool.getConnection();
    while (partitionOfRecords.hasNext()) {
      connection.send(partitionOfRecords.next());
    }
    ConnectionPool.returnConnection(connection); // 为了将来返回到连接池
  });
}); 

请注意,池中的连接应该按需惰性创建,如果不使用一段时间就超时。这样可以最有效地向外部系统发送数据。

还有几点要记住:

  1. DStreams由输出操作惰性执行,就像RDDsRDD操作惰性执行一样。具体来说,DStream输出操作中的RDD操作强制处理接收到的数据。因此,如果应用程序中没有任何输出操作,或者没有任何RDD操作(),那么就不会执行任何操作。系统将简单地接收数据并丢弃它。
  2. 默认情况下,输出操作一次只执行一次。它们按照应用程序中定义的顺序执行。

1foreachRDD

服务端:

客户端:

结果:

2foreach

结果:

3foreachPartitions

结果:

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值