sparkStream-wordCount实现exactlyOne第一种--Mysql

Spark Streaming的Exactly-One的事务处理和不重复输出详解 本篇博文组织形式如下: 一:Exactly-One的事务处理 二:输出不重复一:Exactly-One的事务处理 一:Exactly-One的事务处理 1. 什么是事务处理: a) 能够处理且只被处理一次。例如,银行转账,A转给B,A有且仅转一次。 b) 能够输出,且只能够输出一次。而B接收转账,且直接收一次。2. 事务处理会不会失败呢? 可能性不大,Spark是批处理的方式来进 阅读详情

 

 

主要思路

1、读取历史偏移量

2、根据偏移量加载数据 kafkaUtils.createDirectStream 获取Dstream

3、遍历Dstream  foreachRdd 获取到kafkaRdd

4、从kafkaRdd  as获取当前偏移量 kafkaRdd.asInstanceOf[HasOffsetRanges].offsetRanges

5、开启事务

6、kafkaRdd.value 获取kafka输入的数据

7、rdd转换 处理、将数据写入mysql

8、根据新的偏移量进行偏移量更新

9、提交事务
 

 主方法

package com.ws.sparkstreaming.kafkamysql

import java.sql.Connection

import com.ws.sparkstreaming.utils.{MysqlPool, OffsetUtils}
import org.apache.kafka.clients.consumer.ConsumerRecord
import org.apache.kafka.common.TopicPartition
import org.apache.spark.SparkConf
import org.apache.spark.rdd.RDD
import org.apache.spark.streaming.dstream.InputDStream
import org.apache.spark.streaming.kafka010._
import org.apache.spark.streaming.{Seconds, StreamingContext}

object WordCountJoinKafkaMysqlManagerOffset {
  def main(args: Array[String]): Unit = {
    val name = this.getClass.getSimpleName
    val conf = new SparkConf().setAppName(name).setMaster("local[*]")
    val ssc = new StreamingContext(conf, Seconds(5))
    ssc.sparkContext.setLogLevel("WARN")
    val group = "group2"
    val kafkaParams: Map[String, Object] = Map[String, Object](
      "bootstrap.servers" -> "dream1:9092,dream2:9092,dream3:9092", // kafka地址
      "key.deserializer" -> "org.apache.kafka.common.serialization.StringDeserializer", // 设置反序列化组件
      "value.deserializer" -> "org.apache.kafka.common.serialization.StringDeserializer",
      "group.id" -> group, // 消费者组
      "auto.offset.reset" -> "earliest", // 指定消费者从哪开始消费[latest,earliest]
      "enable.auto.commit" -> "false" // 是否自动提交偏移量,默认是true
    )
    val topic: Iterable[String] = Array("wordcount").toIterable
    // 读取偏移量,要根据gropid和appname来确认offset,如果offset有数据,他会根据我们查到的偏移量,读取kafka数据,否则从头开始读取
    val offset: Map[TopicPartition, Long] = OffsetUtils.selectOffsetFromMysql(name, group)
    val dstream: InputDStream[ConsumerRecord[String, String]] = KafkaUtils.createDirectStream(
      ssc,
      LocationStrategies.PreferConsistent,
      ConsumerStrategies.Subscribe[String, String](topic, kafkaParams, offset)
    )
    dstream.foreachRDD((kafkaRdd: RDD[ConsumerRecord[String, String]]) => {
      // 获取偏移量,为什么偏移量是个array呢???,因为dstram里也是多个kafkardd,一个kafkardd对应一个offsetRange
      val ranges: Array[OffsetRange] = kafkaRdd.asInstanceOf[HasOffsetRanges].offsetRanges
      // 拿到kafkaRdd,先判断是否为空,因为sparkstream,5秒钟就会执行一次,不管有没有数据都会执行,所以先判断rdd内有没有数据
      if (!kafkaRdd.isEmpty()) {
        // 把wordcount写入mysql
        val line: RDD[String] = kafkaRdd.map(_.value().trim)
        val words: RDD[String] = line.flatMap(_.split(" "))
        val wordAnd1: RDD[(String, Int)] = words.map((_, 1))
        val wordAndNums: RDD[(String, Int)] = wordAnd1.reduceByKey(_ + _)
        // 如果想要通过mysql实现exactlyOne 必须要收集到Driver端,在处理,绝对不能在executor端 利用mysql写入数据。因为多个executor是无法控制的
        val res: Array[(String, Int)] = wordAndNums.collect()
        var conn: Connection = null
        try {
          // 获取连接
          conn = MysqlPool.getConnection
          // 开启事务
          conn.setAutoCommit(false)
          // 对收集的数据进行处理,写入数据库
          WordCountMethods.wordcountToMysql(res,conn)
          // 更新偏移量
          OffsetUtils.updateOffsetToMysql(ranges,conn,name,group)
          // 提交事务
          conn.commit()
        } catch {
          case exception: Exception =>
            exception.printStackTrace()
            // 如果错误 回滚
            conn.rollback()
            // 关闭程序
            ssc.stop()
        } finally {
          // 关闭连接
          if (conn != null) {
            conn.close()
          }
        }
      }
    })

    ssc.start()
    ssc.awaitTermination()
  }

}

 mysql连接池

package com.ws.sparkstreaming.utils

import java.sql.Connection
import java.util.Properties

import com.alibaba.druid.pool.DruidDataSourceFactory
import javax.sql.DataSource

object MysqlPool {
  private val prop = new Properties()
  prop.put("driverClassName","com.mysql.jdbc.Driver")
  prop.put("url","jdbc:mysql://dream3:3306/bigdata?characterEncoding=UTF-8")
  prop.put("username","root")
  prop.put("password","root")
  private val source: DataSource = DruidDataSourceFactory.createDataSource(prop)

  def getConnection: Connection ={
    source.getConnection
  }
}

OffsetUtils 偏移量管理工具 

package com.ws.sparkstreaming.utils

import java.sql.Connection

import org.apache.kafka.common.TopicPartition
import org.apache.spark.streaming.kafka010.OffsetRange

import scala.collection.mutable

object OffsetUtils {

  def updateOffsetToMysql(ranges: Array[OffsetRange], conn: Connection, appname: String, goupId: String) = {
    val offsetsql = "insert into spark_stream_offset(app,groupid,topic,`partition`,`offset`) values(?,?,?,?,?) ON DUPLICATE KEY UPDATE offset = ?"
    val ppsm = conn.prepareStatement(offsetsql)
    ranges.foreach(range => {
      ppsm.setString(1, appname)
      ppsm.setString(2, goupId)
      ppsm.setString(3, range.topic)
      ppsm.setInt(4, range.partition)
      ppsm.setLong(5, range.untilOffset)
      ppsm.setLong(6, range.untilOffset)
      ppsm.addBatch()
    })
    ppsm.executeBatch()
  }

  def selectOffsetFromMysql(appname: String, goupId: String): Map[TopicPartition, Long] = {
    val conn = MysqlPool.getConnection
    val offsets = new mutable.HashMap[TopicPartition, Long]()
    val offsetsql = "select `topic`,`partition`,offset from spark_stream_offset where app=? and groupid=?"
    val ppsm = conn.prepareStatement(offsetsql)
    ppsm.setString(1, appname)
    ppsm.setString(2, goupId)
    val set = ppsm.executeQuery()
    while (set.next()) {
      val topic: String = set.getString("topic")
      val partition: Int = set.getInt("partition")
      val offset: Long = set.getLong("offset")
      val part = new TopicPartition(topic, partition)
      offsets.put(part,offset)
    }
    conn.close()
    ppsm.close()
    offsets.toMap
  }

}

 

30分钟概览Spark分布式计算引擎 Spark入门30分钟概览 1、为什么出现Spark? 2、Spark核心是什么? 3、Spark怎么进行分布式计算? 4、Spark在互联网公司的实践应用? 阅读详情

相关推荐

从VoLTE高清通话到5G新通话:手把手带你用Wireshark抓包分析QCI 1, 2, 5, 9的建立与切换过程

本文详细解析了从VoLTE高清通话到5G新通话的QCI(QoS Class Identifier)建立与切换过程,通过Wireshark抓包实战演示如何分析QCI 1、2、5、9的承载机制。内容涵盖QCI基础概念、实验环境搭建、VoLTE通话建立过程分析以及5G新通话中的QoS演进,为网络工程师和通信技术爱好者提供实用的技术指南和优化建议。

weixin_30788619的博客 342

C++实战:从零构建宾馆预定系统,掌握文件存储与业务逻辑设计

数据持久化是软件系统的基础能力,它确保应用状态在程序重启后得以保留。其核心原理是将内存中的数据结构通过序列化技术转换为可存储的格式(如文本或二进制),并写入外部存储介质。在C++工程实践中,这通常涉及文件I/O操作、自定义数据格式设计以及序列化/反序列化逻辑的实现,对于构建不依赖数据库的独立应用程序至关重要。文件存储方案(如CSV格式)因其实现简单、易于调试,常被用于教学项目或配置管理中,它能帮助开发者深入理解数据从内存到磁盘的完整生命周期。基于此,本文聚焦于一个具体的应用场景——城市宾馆预定系统,详细展示

weixin_33739627的博客 450

「免费开源」从 OCR 识别到结构化输出:合同文本高效比对的完整解决方案!

本文将系统拆解这一解决方案的技术逻辑、实施步骤与落地价值,为企业合同管理数字化转型提供实操指南。字段提取:自动识别并提取预设的关键字段(如 “甲方”“乙方”“合同金额”“履约期限” 等),若遇到模糊表述(如 “付款时间为合同签订后 30 个工作日内”),系统可自动解析为 “履约期限:合同签订日 + 30 工作日”;预设结构化字段:根据合同类型(如采购合同、服务合同、租赁合同),定义需提取的关键字段(如 “甲方名称”“乙方名称”“合同金额”“有效期起 / 止日期”“履约地点”“违约金比例” 等);

qxsz_yyh的博客 836

Spark定制班第4课:Spark Streaming的Exactly-One的事务处理和不重复输出彻底掌握

本篇文章主要从二个方面展开: 本期内容 1 Exactly Once 2 输出不重复 1 Exactly Once   事务:   银行转帐为例,A用户转账给B用户,B用户可能收到多笔钱,如何保证事务的一致性,也就是说事务输出,能够输出且只会输出一次,即A只转一次,B只收一次。   从事务视角解密SparkS

andyshar的博客 4366

TEC 高精度控温算法:实现精准升降温与恒温控制

本文深入解析了TEC高精度控温算法的核心原理与工程实践。针对TEC非线性、时变的特性,算法通过智能状态机实现精准升降温与恒温控制,并详细阐述了参数整定、硬件协同及调试优化的系统性方法,为半导体激光器、PCR仪等高精度温控应用提供了一套完整的解决方案。

weixin_29212867的博客 1013

Cisco Secure ACS 5.8.0.32 安装 + Crack 教程

在ESXi 6.7 上经历过无数次的安装尝试测试了各种兼容版本都没有安装成功,记最后一次安装成功的过程.

Junior's Blog 3539

kafka中的端到端一致性(exactly-one)

端到端一致性: exactly-once传输过程要保证exactly-once, 需要内部能够实现状态保存, 当下游保存失败时, 能够更加保存的历史状态再次提交数据.而下游接受数据, 需要具备去重能力. 去重有两种方式:幂等写入, 事务写入内部: 支持checkpoint或者状态保存下一级: 数据不会被重复写入幂等写入根据key去重, 比如k-v数据库: hbase, redis事务写入...

bitbitbyte的博客 1171

【AUTOSAR-E2E】-1.4-详述E2E Transformer解决方案

共13页精讲 目录 1“Data Transformation”介绍 1.1 基于SOME/IP Transformer 1.2 基于COM Based Transformer 2 ComXf(COM Based Transformer)介绍 2.1 ComXf(COM Based Transformer)功能规范 2.2 ComXf(COM Based Transformer)提供的服务 2.3 配置注意事项 3 E2EXf(E2E Transformer)介绍 3.1 E2EX...

「汽车电子助手」的博客 4701

Spark_09

文章目录kafka分区相管知识Spark Streaming原理简介DStream介绍关于nc介绍SparkStreaming整合kafka kafka分区相管知识 Spark Streaming原理简介 DStream介绍 DStream是SparkStream中一个高级的抽象(对RDD的封装)。 关于nc介绍 案例 package day9 import org.apache.spark...

weixin_42581821的博客 286

读懂 ABAP CDS 注解的直接、继承与派生

本文系统梳理了ABAP CDS注解的评估逻辑,重点解析直接注解(Direct)、继承注解(Inherited)和派生注解(Derived)的差异及其在CL_DD_DDL_ANNOTATION_SERVICE中的处理方式。通过视图注解@Metadata.ignorePropagatedAnnotations可调控注解传播行为,避免下游语义影响上层视图。文章还提供了基于标准表的完整示例(包含底层视图、消费视图和ABAP报告程序),帮助开发者在实际系统中验证三层注解的叠加效果与阻断机制。关键点包括:派生注解的数据

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 245

汇川Easy系列PLC系统PID指令编程应用(增量型)

增量式PIDS7-1200/1500增量式PID(输出归一化、支持PWM输出)_西门子1200pid算法公式-优快云博客文章浏览阅读1k次。本文介绍了S7-1200/1500 PLC中增量式PID算法的应用,包括输出归一化和PWM输出。通过详细解析,阐述了PID输出如何限制在0.0-1.0之间,并且如何将PID输出与PWM占空比关联,适用于温度等控制场景。

RXXW_Dor的博客 1426

实时数据仓库-从0到1实时数据仓库设计&实现(SparkStreaming3.x)

实时数据仓库-从0到1实时数据仓库设计&实现(SparkStreaming3.x)

S1124654的博客 2247

R语言缺失值填补|插值法、均值法、邻近法

本文主要介绍如何利用R语言进行数值型缺失值的填补。主要使用zoo包中的na.aggregate() 、na.approx()、na.locf() 函数进行缺失值的均值填补、线性插值填补以及邻近值填补。

Mrrunsen的博客 3843

SparkStreaming读取Kafka的两种方式

原文链接:https://mp.toutiao.com/profile_v4/graphic/preview?pgc_id=6855283208414560780 本文主要从以下几个方面介绍SparkStreaming读取Kafka的两种方式: 一、SparkStreaming简介 二、Kafka简介 三、Redis简介(可用于保存历史数据或偏移量数据) 四、SparkStreaming读取Kafka数据的两种方式 五、演示Demo 一、SparkStreaming简介 可以参考这篇文章:S

静远小和尚的博客 2273

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

SparkStreaming 对接Kafka手动提交偏移量异常

场景: 应业务需求,需使用SparkStreaming 一分钟一批次消费Kafka数据,消费2批次后出现提交偏移量异常 提交代码如下 dataRDD.foreachRDD(rdd=>{ val offsetRanges = rdd.asInstanceOf[HasOffsetRanges].offsetRanges //业务统计 //.... dataRDD.asInstanceOf[CanCommitOffse

lfish001的博客 2267

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

spark streaming窗口函数的使用和理解

spark  streaming中的窗口函数虽然不如flink那么丰富,但是特别有用,看下面例子: kafkaStream.transform { rdd => offsetRanges = rdd.asInstanceOf[HasOffsetRanges].offsetRanges rdd}.map(_._2).map((_, 1)).reduceByKeyAndW

luoyexuge的专栏 1万+

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Streaming+Kafka消费偏移量的维护

如何管理kafka消费偏移量: 一、 kafka消息的位置至关重要,维护其消息偏移量对于避免消息的重复消费与遗漏消费,确保消息的Exactly-once。 kafka的消息所在的位置Topic、Partitions、Offsets三个因素决定。 Kafka消费者消费的消息位置还与consumer的group.id有关。 二、consumerOffsets与earlieastLeaderOffset...

MrGrant.blog 4997

Spark Streaming + Kafka的offset管理

目录简述消费语义offset的三种管理方式offset管理demo自带offset管理将offset存储在MySQL中 简述 Kafka+Spark Streaming主要用于实时流处理。到目前为止,在大数据领域中是一种非常常见的架构。Kafka在其中主要起着一个缓冲的作用,所有的实时数据都会经过kafka。所以对kafka offset的管理是其中至关重要的一环。一但管理不善,就会到导致数据丢失...

夜的博客 1450

Spark Streaming的Exactly-One的事务处理

本博文主要内容: Exactly once容错 数据输出不重复 一、Exactly once:1、 什么是事务处理: a) 能够处理且只被处理一次。例如,银行转账,A转给B,A有且仅转一次。 b) 能够输出,且只能够输出一次。而B接收转账,且直接收一次。Spark Streaming的事务处理和关系型数据库的事务的概念有所不同,关系型数据库事务关注的是语句级别的一致性,例如银行转账。而Spark

吾心光明 1124

spark stream 3.2.1(scala版本)将kafka消费偏移记录到zookeeper

为了实现从kafka读取数据时,避免从头开始的重复读,也避免从最新开始的跳过数据读,有必要在读取数据并处理成功后,记录消费偏移量。当系统重启或者升级维护后,就可以继续从上次处理完成的位置进行继续读取了。

liaomingwu的专栏 605

SparkStreaming - 使用Mysql/Redis手动维护Kafka Offset

Spark Streaming No Receivers 方式的createDirectStream 方法不使用接收器,而是创建输入流直接从Kafka 集群节点拉取消息。输入流保证每个消息从Kafka 集群拉取以后只完全转换一次,保证语义一致性。但是当作业发生故障或重启时,要保障从当前的消费位点去处理数据(即Exactly Once语义),单纯的依靠SparkStreaming本身的机制是不太理想的,生产环境中通常借助手动管理offset的方式来维护kafka的消费位点。本文分享将介绍如何手动管理Kafka

qq_34735235的博客 896

Spark Streaming的Exactly-One的事务处理和不重复输出彻底掌握

Spark Streaming事务处理图分析: 1. Receiver不断地接收数据,收到数据后汇报给driver,driver收到数据后为了数据安全进行checkpoint,checkpoint中有:Configuration,Block MetaData,DStreamGraph,未处理完Job和等待中的Job 2. job的执行完全基于spark core的调试模式 3. Receive

xiaonaughty的博客 942

mysql 词频分析_MapReduce编程实战(2)-词频统计结果存入mysql数据库

摘要通过实现MapReduce计算结果保存到MySql数据库过程,掌握多种方式保存计算结果的技术,加深了对MapReduce的理解;1.master主机安装mysql创建maven项目,项目名称hdfs,这里不再说明。2.修改pom.xml文件红色部分为增加内容:4.0.0com.scitchdfs0.0.1-SNAPSHOTjarhdfshttp://maven.apache.orgUTF-82...

weixin_32633271的博客 347

hive与mysql基本配置与wordcount实例

注:虚拟机如果是最小化安装,请先配置yum源。(这里我就不演示了,自行百度) hive是基于Hadoop的,请先配置Hadoop。 一、mysql配置 若wget不可用,下载安装wget:yum -y install wget 安装后wget http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm 解压rpm -ivh m...

sasa5623的博客 239

spark streaming窗口及聚合操作后如何管理offset

很多知识星球球友问过浪尖一个问题: 就是spark streaming经过窗口的集合操作之后,再去管理offset呢? 对于spark streaming来说窗口操作之后,是无法管理of...

大数据星球-浪尖 1014

第一个MapReduce程序——WordCount

通常我们在学习一门语言的时候,写的第一个程序就是Hello World。而在学习Hadoop时,我们要写的第一个程序就是词频统计WordCount程序。 一、MapReduce简介 1.1 MapReduce编程模型 MapReduce采用”分而治之”的思想,把对大规模数据集的操作,分发给一个主节点管理下的各个分节点共同完成,然后通过整合各个节点的中间结果,得到最终结果。简单地...

dbbaq24022的专栏 3186
上一篇: spark的client模式与cluster模式
下一篇: sparkStream-wordCount实现exactlyOne第二种--Redis
JNWsong
博客等级 码龄9年 287粉丝 204原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值