spark从入门到放弃四十八:Spark Streaming(8)基于kafka 的实时计算

43 篇文章 1 订阅
12 篇文章 1 订阅

文章地址:http://www.haha174.top/article/details/251904
1 基于Receiver 的方式

这种方式使用receiver 来获取数据,Receiver 是使用kafka 的高层次Consumer Api 来实现的,receiver 从kafka 中获取的数据都是存储在Spark Executor 的内存中的,然后Spark Streaming 启动的job 会去处理那些数据。
然而在默认的配置下 这种方式可能会因为底层的失败而丢失数据,如果要启动高可用的可靠机制,让数据零丢失,就必须启动Spark Streaming 的预写日志机制 ,该机制会同步地接收到kafka 数据写入分布式文件系统比如hdfs 上的预写日志中,所以即便底层节点出现了失败,也可以使用预写日志及进行恢复。

kafka中的topic的partition,与spark中的RDD 的partition是没有关系的,所以在kafkaUtils.createStream() 中,提高partition 的数量,只会怎放假一个Receiver中读取数据partition的线程的数量。不会增加spark
处理数据的并行度。

可以创建多个kafka 输入的DStream ,使用不通的consumer group 和topic 来通过receiver 并行的接收数据

如果基于容错的文件系统,比如hdfs 启用了预写日志机制,接收到的数据都会被复制一份到预写的日志中。
下面给出java 示例:

public class KAFKAWorldCount {
    public static void main(String[] args) throws InterruptedException {
        SparkConf conf=new SparkConf().setMaster("local[2]").setAppName("KAFKAWorldCount");
        JavaStreamingContext jssc=new JavaStreamingContext(conf, Durations.seconds(5));
        Map<String,Integer> map=new HashMap<>();
        map.put("worldCount",1);
        JavaPairReceiverInputDStream<String,String> lines= KafkaUtils.createStream(jssc,"cloud.codeguoj.cn:2181","DefaultConsumerGroup",map);
        JavaDStream<String> worlds=lines.flatMap(new FlatMapFunction<Tuple2<String, String>, String>() {
            @Override
            public Iterator<String> call(Tuple2<String, String> stringStringTuple2) throws Exception {
                return Arrays.asList(stringStringTuple2._2.split(" ")).iterator();
            }
        });
        JavaPairDStream<String,Integer> linePair=worlds.mapToPair(new PairFunction<String, String, Integer>() {
            @Override
            public Tuple2<String, Integer> call(String s) throws Exception {
                return new Tuple2<String, Integer>(s,1);
            }
        });

        JavaPairDStream<String,Integer> lineWorldCount=linePair.reduceByKey(new Function2<Integer, Integer, Integer>() {
            @Override
            public Integer call(Integer v1, Integer v2) throws Exception {
                return v1+v2;
            }
        });
        lineWorldCount.print();
        jssc.start();
        jssc.awaitTermination();
        jssc.stop();
        jssc.close();
    }
}

2 基于Direct 的方式

这种不基于Receiver 的直接方式 能够保证更加健壮的机制,替代掉使用Receiver 来接收数据后,从这种方式会周期性地查询kafka ,来获得每个topic+partition 的最新的offset 从而定义每个batch 的offset 的范围,当处理数据的job 启动的时候就会使用kafka 的简单的consumer api 来获取kafka 指定的offset 范围的数据

这种方式有如下优点:
1.简化并行读取:如果要读取多额partition 不需要创建多个DStream 然后对他们进行union 的操作。spark 会创建跟kafka partition 一样多的RDD partition 并且会并行从kafka 中读取数据,所以kakfa partition 和RDD partition 之间,有一个一对一的映射关系。
2.高性能:如果要保证零数据丢失,在基于receiver 的方式种需要开启WAL 机制。这种方式其实效率低下,因为数据实际上被复制了两份,kafka 自己本地就有高可靠的机制,会对数据复制一份,而这里又会复制一份到WAL 中,而基于direct 的方式,不依赖Receiver ,不需要开启WAL 机制,只要kafka 中做了数据的复制,那么就可以通过kafka 的副本进行恢复。
3.一次且仅一次的事务机制
基于receiver 的方式,是使用kafka 的高阶api 来zookeeper 中保存消费过的offset 。这是消费kafka 数据的传统方式,这种方式配合着wal 机制可以保证数据零丢失的高可靠性,但是却无法保证数据被处理一次且仅一次,可能会处理两次因为spark和zookeeepr 之间是不同步的
基于direct 的方式使用kafka 的简单的api spark Streaming 自己就负责追踪消费的offset 并保存在checkpoint 中spark 自己一定是同步的,因此可以保证消费因此且仅消费一次。
下面给出java 示例:

public class KAFKADriectWorldCount {
    public static void main(String[] args) throws InterruptedException {
        SparkConf conf=new SparkConf().setMaster("local[2]").setAppName("KAFKAWorldCount");
        JavaStreamingContext jssc=new JavaStreamingContext(conf, Durations.seconds(5));
        Map<String,String> map=new HashMap<>();
        map.put("metadata.broker.list","cloud.codeguoj.cn:9092");
        Set<String> toPics=new HashSet<>();
        toPics.add("worldCount");
        JavaPairInputDStream<String,String> lines= KafkaUtils.createDirectStream(jssc,
                String.class,
                String.class,
                StringDecoder.class,
                StringDecoder.class,
                map,
                toPics);
        JavaDStream<String> worlds=lines.flatMap(new FlatMapFunction<Tuple2<String, String>, String>() {
            @Override
            public Iterator<String> call(Tuple2<String, String> stringStringTuple2) throws Exception {
                return Arrays.asList(stringStringTuple2._2.split(" ")).iterator();
            }
        });
        JavaPairDStream<String,Integer> linePair=worlds.mapToPair(new PairFunction<String, String, Integer>() {
            @Override
            public Tuple2<String, Integer> call(String s) throws Exception {
                return new Tuple2<String, Integer>(s,1);
            }
        });

        JavaPairDStream<String,Integer> lineWorldCount=linePair.reduceByKey(new Function2<Integer, Integer, Integer>() {
            @Override
            public Integer call(Integer v1, Integer v2) throws Exception {
                return v1+v2;
            }
        });
        lineWorldCount.print();
        jssc.start();
        jssc.awaitTermination();
        jssc.stop();
        jssc.close();
    }
}

欢迎关注,更多惊喜等着你

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据实时计算系统是如今互联网行业中非常重要的一个领域,本篇文章将介绍一个基于Java、KafkaSpark Streaming的大数据实时计算系统,该系统能够实时地处理海量的数据,并且对数据进行实时分析和处理,从而为用户提供有价值的数据分析和预测服务。 一、系统架构设计 系统的整体架构如下图所示: ![系统架构设计图](https://img-blog.csdnimg.cn/20220105104312759.png) 从上图可以看出,整个系统分为四个主要模块: 1. 数据采集模块:该模块负责采集用户的行为数据,并将数据发送到Kafka消息队列中。 2. 数据处理模块:该模块负责从Kafka消息队列中读取数据,并对数据进行实时处理和分析,从而生成有价值的数据。 3. 数据存储模块:该模块负责将处理后的数据存储到HDFS分布式文件系统中,以便后续进行离线分析和处理。 4. 数据展示模块:该模块负责将处理后的数据展示给用户,提供数据分析和预测服务。 二、系统模块详细设计 1. 数据采集模块 数据采集模块主要负责采集用户的行为数据,并将数据发送到Kafka消息队列中。采集模块使用Java编写,主要包括以下几个模块: - 数据采集模块:负责采集用户的行为数据,并将数据发送到Kafka消息队列中。 - 数据发送模块:负责将采集到的数据发送到Kafka消息队列中。 - 配置文件模块:负责读取系统配置文件,包括Kafka消息队列的配置信息等。 2. 数据处理模块 数据处理模块主要负责从Kafka消息队列中读取数据,并对数据进行实时处理和分析,从而生成有价值的数据数据处理模块使用Spark Streaming框架编写,主要包括以下几个模块: - 数据读取模块:负责从Kafka消息队列中读取数据,并转化为Spark Streaming中的DStream数据结构。 - 数据处理模块:负责对DStream数据进行实时处理和分析,从而生成有价值的数据。 - 数据输出模块:负责将处理后的数据输出到HDFS分布式文件系统中。 - 配置文件模块:负责读取系统配置文件,包括Kafka消息队列的配置信息、Spark Streaming框架的配置信息等。 3. 数据存储模块 数据存储模块主要负责将处理后的数据存储到HDFS分布式文件系统中,以便后续进行离线分析和处理。数据存储模块使用Hadoop HDFS编写,主要包括以下几个模块: - 数据写入模块:负责将处理后的数据写入到HDFS分布式文件系统中。 - 数据读取模块:负责从HDFS分布式文件系统中读取数据进行离线分析和处理。 - 配置文件模块:负责读取系统配置文件,包括HDFS的配置信息等。 4. 数据展示模块 数据展示模块主要负责将处理后的数据展示给用户,提供数据分析和预测服务。数据展示模块使用Web开发技术编写,主要包括以下几个模块: - 数据展示模块:负责将处理后的数据展示给用户,提供数据分析和预测服务。 - 数据查询模块:负责从HDFS分布式文件系统中查询数据进行展示。 - 配置文件模块:负责读取系统配置文件,包括Web服务的配置信息等。 三、系统运行流程 1. 数据采集模块从用户端采集数据,并将数据发送到Kafka消息队列中。 2. 数据处理模块从Kafka消息队列中读取数据,并进行实时处理和分析。 3. 数据处理模块将处理后的数据输出到HDFS分布式文件系统中。 4. 数据展示模块从HDFS分布式文件系统中读取数据进行展示,提供数据分析和预测服务。 四、系统优化 为了提高系统的性能和稳定性,我们可以采取以下几个优化措施: 1. 数据处理模块使用Spark Streaming框架,能够实现高效的实时数据处理和分析。 2. 数据存储模块使用Hadoop HDFS分布式文件系统,具有高可靠性和高扩展性。 3. 数据展示模块可以采用分布式Web服务架构,提高系统的并发处理能力。 4. 系统的各个模块之间采用异步通信机制,能够提高系统的并发性和响应速度。 五、总结 本文简要介绍了一个基于Java、KafkaSpark Streaming的大数据实时计算系统,该系统能够实时地处理海量的数据,并且对数据进行实时分析和处理,从而为用户提供有价值的数据分析和预测服务。通过优化系统架构和技术选型,能够提高系统的性能和稳定性,为用户提供更好的服务。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值