这篇博客帮你开始使用Apache Spark Streaming和HBase。Spark Streaming是核心Spark API的一个扩展,它能够处理连续数据流。

Spark Streaming是什么?

首先,Spark Streaming是什么?数据流是数据连续到来的无限序列。Streaming划分连续流动的输入数据成离散单元以便处理。流处理是对流数据的低延迟处理和分析。Spark Streaming是核心Spark API的一个扩展,能够允许对实时数据的可扩展,高吞吐量,容错流处理。Spark Streaming用于需要快速处理实时到来的大数据量的应用情形。

实时应用情形的实例有以下场合:

  • 网络站点监控,网络监控
  • 欺诈侦测
  • 网络点击
  • 广告
  • 物联网传感器

Spark Streaming支持的数据源有:HDFS directories, TCP sockets, Kafka, Flume, Twitter等等。Data Streams能被Spark的核心APIS,DataFrames SQL,或机器学习APIs,来处理,还能够持久化到文件系统,HDFS,数据库,或任何提供Hadoop OutputFormat的数据源。

Spark Streaming是怎么运行的

Spark Streaming划分一个数据流成X秒一组的数据,它被称为Dstreams,本质上是RDDs的一个序列。你的Spark应用程序使用Spark APIs处理RDDs,RDD操作的处理结果成批地返回。

一个Streaming应用实例的架构

Spark Streaming实例代码完成了以下操作:

  • 读流数据
  • 处理流数据
  • 将处理过的数据写入到HBase Table

另外的Spark实例代码会执行下面操作:

  • 读取由streaming代码写入的HBase Table数据
  • 计算每日的汇总统计结果
  • 将统计结果写入到HBase Table Column Family stats(HBase Table统计列族)

样本数据集

油量泵传感器数据来自于目录中一个逗号分隔值(csv)文件。Spark Streaming监控那个目录,并处理目录中创建的任何文件。(正如之前提到的,Spark Streaming支持不同的流数据源;为了简单化,这个例子使用了文件。)下面是csv文件样本数据的一个例子:

我们使用Scala 样本类(case class)定义对应于传感器数据csv文件的传感器数据库模式,使用一个parseSensor函数去解析在传感器样本类(case class)中的逗号分隔值。

HBase Table Schema

流数据的HBase Table Schema如下:

  • 泵名称日期和时间戳的复合行键。
  • 列中的Column Family数据对应于输入数据域,Column Family告警列对应于警报值筛选器。注意,经过一定时间后,数据和告警列集会被设置成终止值。

日常统计数据汇总归纳的Schema列举如下:

  • 泵名称和日期的复合行键。
  • 统计列族(Column Family stats)
  • 最小列,最大列,平均列

下面的函数转换一个Sensor 对象成为一个HBase Put对象,用于往HBase插入一行。

写入一个HBase Table的配置

你可以使用Spark中的TableOutputFormat 类来写一个HBase Table,类似于你怎样从MapReduce 往HBase Table中写数据。下面我们使用TableOutputFormat类来设置要往HBase中写的配置。

Spark Streaming例子代码

这些是Spark Streaming代码的基本步骤:

1.初始化一个Spark StreamingContext对象;

2.对DStreams应用转换和输出操作;

3.使用streamingContext.start()来开始接收数据和处理;

4.使用streamingContext.awaitTermination()来等待处理过程停止;

我们会使用实际的应用程序代码完成上面的每一步。

初始化StreamingContext

首先,我们创建一个StreamingContext,它是流功能函数主入口点,是有一个两秒批间隔

val sparkConf = new SparkConf().setAppName("HBaseStream")
//  create a StreamingContext, the main entry point for all streaming functionality
val ssc = new StreamingContext(sparkConf, Seconds(2))

下一步,我们使用StreamingContext textFileStream(目录) 方法创建输入流,它用于监控Hadoop-兼容(Hadoop-compatible)的文件系统,文件系统用于新文件,输入流也处理在这个目录下任何文件创建的操作。

// create a DStream that represents streaming data from a directory source
val linesDStream = ssc.textFileStream("/user/user01/stream")

那个linesDStream代表数据流,每条记录是文本中的一行。本质上,DStream 是RDDs的一个序列,代表每批次间隔的一个RDD。

对DStreams应用转换和输出操作

接着,我们解析数据行成Sensor对象,对linesDStream使用映射操作.

// parse each line of data in linesDStream  into sensor objects
val sensorDStream = linesDStream.map(Sensor.parseSensor)

映射操作使用Sensor.parseSensor函数对linesDStream中的RDDs进行操作,获得了RDDs of Sensor对象。

接下来,我们使用DStream的 foreachRDD方法去对这个DStream中的每个RDD进行处理。我们筛选那个传感器对象到适合的低压力值去创建告警,通过转换它们成Put对象来将传感器和告警数据写入到HBase中,接着使用PairRDDFunctions 的saveAsHadoopDataset方法,输出RDD到支持Hadoop的任何存储系统,那个存储系统使用一个Hadoop Configuration对象(查看上面的HBase的Hadoop Configuration)。

// for each RDD. performs function on each RDD in DStream
sensorRDD.foreachRDD { rdd =>
        // filter sensor data for low psi
     val alertRDD = rdd.filter(sensor => sensor.psi < 5.0)
      // convert sensor data to put object and write to HBase  Table CF data
      rdd.map(Sensor.convertToPut).saveAsHadoopDataset(jobConfig)
     // convert alert to put object write to HBase  Table CF alerts
     rdd.map(Sensor.convertToPutAlert).saveAsHadoopDataset(jobConfig)
}

那个传感器RDD对象被转换成Put对象,然后写入HBase。

开始接收数据

为了开始接收数据,我们必须在StreamingContext中显式地调用start(),然后调用awaitTermination去等待流计算直到它终止。

// Start the computation
    ssc.start()
    // Wait for the computation to terminate
    ssc.awaitTermination()

从Spark中读取和写回HBase

现在我们想要读取HBase传感器表数据,计算每日汇总统计数据,将统计数据写到统计列族。

下面的代码读取HBase传感器表压力列数据,使用StatCounter计算这个数据的统计值,将统计数据写入到传感器统计列族。

    // configure HBase for reading
    val conf = HBaseConfiguration.create()
    conf.set(TableInputFormat.INPUT_TABLE, HBaseSensorStream.tableName)
    // scan data column family psi column
    conf.set(TableInputFormat.SCAN_COLUMNS, "data:psi")
// Load an RDD of (row key, row Result) tuples from the table
    val hBaseRDD = sc.newAPIHadoopRDD(conf, classOf[TableInputFormat],
      classOf[org.apache.hadoop.hbase.io.ImmutableBytesWritable],
      classOf[org.apache.hadoop.hbase.client.Result])
    // transform (row key, row Result) tuples into an RDD of Results
    val resultRDD = hBaseRDD.map(tuple => tuple._2)
    // transform into an RDD of (RowKey, ColumnValue)s , with Time removed from row key
    val keyValueRDD = resultRDD.
              map(result => (Bytes.toString(result.getRow()).
              split(" ")(0), Bytes.toDouble(result.value)))
    // group by rowkey , get statistics for column value
    val keyStatsRDD = keyValueRDD.
             groupByKey().
             mapValues(list => StatCounter(list))
    // convert rowkey, stats to put and write to hbase table stats column family
    keyStatsRDD.map { case (k, v) => convertToPut(k, v) }.saveAsHadoopDataset(jobConfig)

下面这个图显示了newAPIHadoopRDD的输出是一个RDD行键值,成对出现。那个PairRDDFunctions的 saveAsHadoopDataset方法保存Put对象到HBase中。

软件

这个示例运行在MapR  Sandbox上,包含了Spark。

你可以从下面网址下载代码和数据来运行这个例子:https://github.com/caroljmcdonald/SparkStreamingHBaseExample

运行程序

你可以运行那些代码作为一个独立应用程序,正如Getting Started with Spark on MapR Sandbox示例中所描述的。

这里是步骤总结:

  • 使用用户名user01,密码mapr登录MapR  Sandbox, 正如Getting Started with Spark on MapR Sandbox所描述的。
  • 使用Maven编译应用程序。
  • 使用scp命令拷贝jar文件和数据文件到你的sandbox根目录/user/user01。
  • 执行流app:
    /opt/mapr/spark/spark-<version>/bin/spark-submit --driver-class-path `hbase classpath`
    --class examples.HBaseSensorStream sparkstreamhbaseapp-1.0.jar
  • 拷贝流数据文件到流目录:
    cp sensordata.csv /user/user01/stream/
  • 读数据计算一列的统计数据:
    /opt/mapr/spark/spark-<version>/bin/spark-submit --driver-class-path `hbase classpath`
    --class examples.HBaseReadWrite sparkstreamhbaseapp-1.0.jar
  • 计算整行的统计数据:
    /opt/mapr/spark/spark-<version>/bin/spark-submit --driver-class-path `hbase classpath`
    --class examples.HBaseReadRowWriteStats sparkstreamhbaseapp-1.0.jar

结语

关于Spark Streaming with HBase的示例叙述就结束了。在以下参考部分,你可以找到更多信息。

Getting Started with Apache Spark: From Inception to Production Book

Apache Spark Streaming Programming guide

Learning Spark O’Reilly Book

Databricks Spark Streaming

Spark Streaming 入门指南的更多相关文章

  1. Apache Spark 2.2.0 中文文档 - Spark Streaming 编程指南 | ApacheCN

    Spark Streaming 编程指南 概述 一个入门示例 基础概念 依赖 初始化 StreamingContext Discretized Streams (DStreams)(离散化流) Inp ...

  2. Spark Streaming入门

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文将帮助您使用基于HBase的Apache Spark Streaming.Spark Streaming是Spark API核心的一个扩 ...

  3. [转] Spark快速入门指南 – Spark安装与基础使用

    [From] https://blog.csdn.net/w405722907/article/details/77943331 Spark快速入门指南 – Spark安装与基础使用 2017年09月 ...

  4. Apache Spark 2.2.0 中文文档 - Spark Streaming 编程指南

    Spark Streaming 编程指南 概述 一个入门示例 基础概念 依赖 初始化 StreamingContext Discretized Streams (DStreams)(离散化流) Inp ...

  5. spark streaming 入门例子

    spark streaming 入门例子: spark shell import org.apache.spark._ import org.apache.spark.streaming._ sc.g ...

  6. Spark高速入门指南(Quick Start Spark)

    版权声明:本博客已经不再更新.请移步到Hadoop技术博客:https://www.iteblog.com https://blog.csdn.net/w397090770/article/detai ...

  7. Spark Streaming编程指南

    Overview A Quick Example Basic Concepts Linking Initializing StreamingContext Discretized Streams (D ...

  8. Spark Streaming 入门

    概述 什么是 Spark Streaming? Spark Streaming is an extension of the core Spark API that enables scalable, ...

  9. Spark基础:(七)Spark Streaming入门

    介绍 1.是spark core的扩展,针对实时数据流处理,具有可扩展.高吞吐量.容错. 数据可以是来自于kafka,flume,tcpsocket,使用高级函数(map reduce filter ...

随机推荐

  1. oracle中的function 、procedure、packages、package bodies比较

    1  function和procedure的区别 1).可以理解函数是存储过程的一种 2).函数可以没有参数,但是一定需要一个返回值,存储过程可以没有参数,不需要返回值 3).函数return返回值没 ...

  2. [Codeforces 501D] - Misha and Permutations Summation

    题意是给你两个长度为$n$的排列,他们分别是$n$的第$a$个和第$b$个全排列.输出$n$的第$\left(a+b \right)\textrm{mod} \, n!$个全排列. 一种很容易的想法是 ...

  3. 【转】overload与override的区别

    [转]overload与override的区别 override(重写,覆盖) 1.方法名.参数.返回值相同. 2.子类方法不能缩小父类方法的访问权限. 3.子类方法不能抛出比父类方法更多的异常(但子 ...

  4. GridView点击行,选中模版列中CheckBox

    <asp:TemplateField ItemStyle-Width="40px" HeaderText="选择" ItemStyle-Horizonta ...

  5. 各浏览器对 onbeforeunload 事件的支持与触发条件实现有差异

    转载:http://www.w3help.org/zh-cn/causes/BX2047 标准参考 无. 问题描述 一般情况下,onbeforeunload 事件处理函数内会写入一些提示性语句,当用户 ...

  6. Ext checkbox

    Ext.require([     'Ext.grid.*',     'Ext.data.*',     'Ext.util.*',     'Ext.grid.PagingScroller',   ...

  7. iOS开发实现登陆

    Assumption假设:iOS端加载Web页,然后用户输入用户名密码登陆,WebServer会把用户登陆信息记载在Cookie.那么iOS客户端如何取到Cookie中的登陆信息. 客户端监听 NSH ...

  8. CocoaPods使用详细说明(转)

    一.概要 iOS开发时,项目中会引用许多第三方库,CocoaPods(https://github.com/CocoaPods/CocoaPods)可以用来方便的统一管理这些第三方库. 二.安装 由于 ...

  9. JavaScript 字符串

    字符串属性 属性 描述 constructor 返回创建字符串属性属性的函数 length 返回字符串的长度 prototype 允许您向对象添加属性和方法 字符串方法 Method 描述 charA ...

  10. SqlDependency 的使用

    1.SqlDependency是什么: SqlDependency 对象表示应用程序和 SQL Server 实例间的查询通知依赖关系.应用程序可以创建一个 SqlDependency 对象并进行注册 ...