使用 Kafka + Spark Streaming + Cassandra 构建数据实时处理引擎
Apache Kafka 是一个可扩展,高性能,低延迟的平台,允许我们像消息系统一样读取和写入数据。我们可以很容易地在 Java 中使用 Kafka。
Spark Streaming 是 Apache Spark 的一部分,是一个可扩展、高吞吐、容错的实时流处理引擎。虽然是使用 Scala 开发的,但是支持 Java API。
Apache Cassandra 是分布式的 NoSQL 数据库。
准备
在进行下面文章介绍之前,我们需要先创建好 Kafka 的主题以及 Cassandra 的相关表,具体如下:
在 Kafka 中创建名为 messages 的主题
$KAFKA_HOME$\bin\windows\kafka-topics.bat --create \ --zookeeper localhost:2181 \ --replication-factor 1 --partitions 1 \ --topic messages |
在 Cassandra 中创建 KeySpace 和 table
CREATE KEYSPACE vocabulary WITH REPLICATION = { 'class' : 'SimpleStrategy' , 'replication_factor' : 1 }; USE vocabulary; CREATE TABLE words (word text PRIMARY KEY, count int); |
上面我们创建了名为 vocabulary 的 KeySpace,以及名为 words 的表。
添加依赖
我们使用 Maven 进行依赖管理,这个项目使用到的依赖如下:
< dependency > < groupId >org.apache.spark</ groupId > < artifactId >spark-core_2.11</ artifactId > < version >2.3.0</ version > < scope >provided</ scope > </ dependency > < dependency > < groupId >org.apache.spark</ groupId > < artifactId >spark-sql_2.11</ artifactId > < version >2.3.0</ version > < scope >provided</ scope > </ dependency > < dependency > < groupId >org.apache.spark</ groupId > < artifactId >spark-streaming_2.11</ artifactId > < version >2.3.0</ version > < scope >provided</ scope > </ dependency > < dependency > < groupId >org.apache.spark</ groupId > < artifactId >spark-streaming-kafka-0-10_2.11</ artifactId > < version >2.3.0</ version > </ dependency > < dependency > < groupId >com.datastax.spark</ groupId > < artifactId >spark-cassandra-connector_2.11</ artifactId > < version >2.3.0</ version > </ dependency > < dependency > < groupId >com.datastax.spark</ groupId > < artifactId >spark-cassandra-connector-java_2.11</ artifactId > < version >1.5.2</ version > </ dependency > |
数据管道开发
我们将使用 Spark 在 Java 中创建一个简单的应用程序,它将与我们之前创建的Kafka主题集成。应用程序将读取已发布的消息并计算每条消息中的单词频率。 然后将结果更新到 Cassandra 表中。整个数据架构如下:
现在我们来详细介绍代码是如何实现的。
获取 JavaStreamingContext
Spark Streaming 中的切入点是 JavaStreamingContext,所以我们首先需要获取这个对象,如下:
SparkConf sparkConf = new SparkConf(); sparkConf.setAppName( "WordCountingApp" ); sparkConf.set( "spark.cassandra.connection.host" , "127.0.0.1" ); JavaStreamingContext streamingContext = new JavaStreamingContext( sparkConf, Durations.seconds( 1 )); |
从 Kafka 中读取数据
有了 JavaStreamingContext 之后,我们就可以从 Kafka 对应主题中读取实时流数据,如下:
Map<String, Object> kafkaParams = new HashMap<>(); kafkaParams.put( "bootstrap.servers" , "localhost:9092" ); kafkaParams.put( "key.deserializer" , StringDeserializer. class ); kafkaParams.put( "value.deserializer" , StringDeserializer. class ); kafkaParams.put( "group.id" , "use_a_separate_group_id_for_each_stream" ); kafkaParams.put( "auto.offset.reset" , "latest" ); kafkaParams.put( "enable.auto.commit" , false ); Collection<String> topics = Arrays.asList( "messages" ); JavaInputDStream<ConsumerRecord<String, String>> messages = KafkaUtils.createDirectStream( streamingContext, LocationStrategies.PreferConsistent(), ConsumerStrategies.<String, String> Subscribe(topics, kafkaParams)); |
我们在程序中提供了 key 和 value 的 deserializer。这个是 Kafka 内置提供的。我们也可以根据自己的需求自定义 deserializer。
处理 DStream
我们在前面只是定义了从 Kafka 中哪张表中获取数据,这里我们将介绍如何处理这些获取的数据:
JavaPairDStream<String, String> results = messages .mapToPair( record -> new Tuple2<>(record.key(), record.value()) ); JavaDStream<String> lines = results .map( tuple2 -> tuple2._2() ); JavaDStream<String> words = lines .flatMap( x -> Arrays.asList(x.split( "\\s+" )).iterator() ); JavaPairDStream<String, Integer> wordCounts = words .mapToPair( s -> new Tuple2<>(s, 1 ) ).reduceByKey( (i1, i2) -> i1 + i2 ); |
将数据发送到 Cassandra 中
最后我们需要将结果发送到 Cassandra 中,代码也很简单。
wordCounts.foreachRDD( javaRdd -> { Map<String, Integer> wordCountMap = javaRdd.collectAsMap(); for (String key : wordCountMap.keySet()) { List<Word> wordList = Arrays.asList( new Word(key, wordCountMap.get(key))); JavaRDD<Word> rdd = streamingContext.sparkContext().parallelize(wordList); javaFunctions(rdd).writerBuilder( "vocabulary" , "words" , mapToRow(Word. class )).saveToCassandra(); } } ); |
启动应用程序
最后,我们需要将这个 Spark Streaming 程序启动起来,如下:
streamingContext.start(); streamingContext.awaitTermination(); |
使用 Checkpoints
在实时流处理应用中,将每个批次的状态保存下来通常很有用。比如在前面的例子中,我们只能计算单词的当前频率,如果我们想计算单词的累计频率怎么办呢?这时候我们就可以使用 Checkpoints。新的数据架构如下
为了启用 Checkpoints,我们需要进行一些改变,如下:
streamingContext.checkpoint( "./.checkpoint" ); |
这里我们将 checkpoint 的数据写入到名为 .checkpoint 的本地目录中。但是在现实项目中,最好使用 HDFS 目录。
现在我们可以通过下面的代码计算单词的累计频率:
JavaMapWithStateDStream<String, Integer, Integer, Tuple2<String, Integer>> cumulativeWordCounts = wordCounts .mapWithState( StateSpec.function( (word, one, state) -> { int sum = one.orElse( 0 ) + (state.exists() ? state.get() : 0 ); Tuple2<String, Integer> output = new Tuple2<>(word, sum); state.update(sum); return output; } ) ); |
部署应用程序
最后,我们可以使用 spark-submit 来部署我们的应用程序,具体如下:
$SPARK_HOME$\bin\spark-submit \ --class com.baeldung.data.pipeline.WordCountingAppWithCheckpoint \ --master local [2] \target\spark-streaming-app-0.0.1-SNAPSHOT-jar-with-dependencies.jar |
最后,我们可以在 Cassandra 中查看到对应的表中有数据生成了。完整的代码可以参见 https://github.com/eugenp/tutorials/tree/master/apache-spark
使用 Kafka + Spark Streaming + Cassandra 构建数据实时处理引擎的更多相关文章
- Kafka:ZK+Kafka+Spark Streaming集群环境搭建(十一)定制一个arvo格式文件发送到kafka的topic,通过Structured Streaming读取kafka的数据
将arvo格式数据发送到kafka的topic 第一步:定制avro schema: { "type": "record", "name": ...
- Apache Kafka + Spark Streaming Integration
1.目标 为了构建实时应用程序,Apache Kafka - Spark Streaming Integration是最佳组合.因此,在本文中,我们将详细了解Kafka中Spark Streamin ...
- Kafka:ZK+Kafka+Spark Streaming集群环境搭建(十)安装hadoop2.9.0搭建HA
如何搭建配置centos虚拟机请参考<Kafka:ZK+Kafka+Spark Streaming集群环境搭建(一)VMW安装四台CentOS,并实现本机与它们能交互,虚拟机内部实现可以上网.& ...
- Kafka:ZK+Kafka+Spark Streaming集群环境搭建(九)安装kafka_2.11-1.1.0
如何搭建配置centos虚拟机请参考<Kafka:ZK+Kafka+Spark Streaming集群环境搭建(一)VMW安装四台CentOS,并实现本机与它们能交互,虚拟机内部实现可以上网.& ...
- Kafka:ZK+Kafka+Spark Streaming集群环境搭建(二)安装hadoop2.9.0
如何搭建配置centos虚拟机请参考<Kafka:ZK+Kafka+Spark Streaming集群环境搭建(一)VMW安装四台CentOS,并实现本机与它们能交互,虚拟机内部实现可以上网.& ...
- demo2 Kafka+Spark Streaming+Redis实时计算整合实践 foreachRDD输出到redis
基于Spark通用计算平台,可以很好地扩展各种计算类型的应用,尤其是Spark提供了内建的计算库支持,像Spark Streaming.Spark SQL.MLlib.GraphX,这些内建库都提供了 ...
- 日志=>flume=>kafka=>spark streaming=>hbase
日志=>flume=>kafka=>spark streaming=>hbase 日志部分 #coding=UTF-8 import random import time ur ...
- Spark Streaming揭秘 Day16 数据清理机制
Spark Streaming揭秘 Day16 数据清理机制 今天主要来讲下Spark的数据清理机制,我们都知道,Spark是运行在jvm上的,虽然jvm本身就有对象的自动回收工作,但是,如果自己不进 ...
- Kafka:ZK+Kafka+Spark Streaming集群环境搭建(二十一)NIFI1.7.1安装
一.nifi基本配置 1. 修改各节点主机名,修改/etc/hosts文件内容. 192.168.0.120 master 192.168.0.121 slave1 192.168.0.122 sla ...
随机推荐
- 【常用工具】vagrant的box哪里下?镜像在哪儿找?教你在vagrant官网下载各种最新.box资源
进入vagrant官网 : https://www.vagrantup.com/ 点击findbox[寻找box],进入有很多box的列表 : https://app.vagrantup.com/bo ...
- Collection接口和list,set子类
Collection接口常用的子接口有:List接口.Set接口List接口常用的子类有:ArrayList类.LinkedList类Set接口常用的子类有:HashSet类.LinkedHashSe ...
- 在Cent OS云服务器上部署基于TP5后端代码踩坑记录_艾孜尔江撰
推荐使用镜像安装Cent OS系统,或者在纯净安装完成之后在完成Apache+MySQL+PHP的时候不要每个单独安装,因为这样会出一些三者之间版本不配的问题,网上各种说法都有,查起来也非常困难,版本 ...
- [Objective-C] 008_Foundation框架之NSArray与NSMutableArray
在Cocoa Foundation中NSArray和NSMutableArray 用于对象有序集合,NSArray和NSMutableArray类最大的区别是:NSArray是不可变,NSMutabl ...
- win服务器管理系统全面升级,教您如何成为运维达人
作为服务器运维人员都知道,日常检查服务器问题并处理问题几乎占据了所有时间,检查服务器的繁琐也只有他们自己能体会,这些外界看似的“工作本分职责”,真是有苦难言.为此我专门研究了市面上三款主打的服务器管理 ...
- Chisel3 - model - DefWire, Reg, Memory, Prim
https://mp.weixin.qq.com/s/KkkqvekWHG6yrqwHUECRIw 介绍如何定义Wire/Reg/Memory/Prim. 1. DefWire Wire( ...
- jchdl - GSL实例 - Counter
https://mp.weixin.qq.com/s/BjQtQE8DfaKP1XwcTiCwVg 摘自康华光<电子技术基础 · 数字部分>(第五版) 参考链接 https: ...
- IDEA字节码学习查看神器jclasslib bytecode viewer介绍
转载来自:https://blog.csdn.net/w605283073/article/details/103209221 一.背景 很多人想学习Java反汇编后的字节码,但是一方面缺乏好的资料, ...
- Java实现 LeetCode 768 最多能完成排序的块 II(左右便利)
768. 最多能完成排序的块 II 这个问题和"最多能完成排序的块"相似,但给定数组中的元素可以重复,输入数组最大长度为2000,其中的元素最大为10**8. arr是一个可能包含 ...
- Java实现 LeetCode 721 账户合并(并查集)
721. 账户合并 给定一个列表 accounts,每个元素 accounts[i] 是一个字符串列表,其中第一个元素 accounts[i][0] 是 名称 (name),其余元素是 emails ...