Spark项目实战经验

1.参数设置

spark.streaming.kafka.maxRatePerPartition 控制spark streaming消费kafka速度
spark.streaming.backpressure.enabled 打开背压消费速度是动态浮动的,上限由spark.streaming.kafka.maxRatePerPartition决定
spark.streaming.stopGracefullyOnShutdown 优雅关闭 防止程序处理数据处理一般被kill 调用yarn application -kill 命令关闭
Spark Configuration官方说明

2.偏移量设置

auto.offset.reset 启动时读取的偏移量。如果是需要历史数据那么设置成earliest 如果不需要消费历史数据那么设置成latest

3.提交偏移量的问题

(1)如果自动提交偏移量 spark streaming消费到数据之后立马提交,那么就会有一个问题 提交偏移量成功 处理失败了,那么spark streaming第二次去启动的时候
会造成丢数据的情况
(2)如果不允许数据丢失,首先要设置成手动提交,处理完业务数据之后在去提交一个偏移量。因为处理业务数据这一步骤它是worker端分布式的,提交偏移量操作是在driver端,两部分操作不在一个事务里面,所以造成处理数据成功了,提交偏移量失败了(停电,断网 极端情况下)会造成spark streaming第二次启动的时候造成数据重复消费的问题 。
涉及到金额的情况下会去考虑一个事物的问题,绑定事物操作worder端将数据collect聚合到driver端再去编写同一个事物,一般情况下是不考虑事物的。Spark当中凡事count ,collect这些会将数据聚合到driver的算子一般不推荐使用,耗时非常大。

4.创建DStream

使用KafkaUtils.createDirectStream这个方法创建,该方法使每个executer直接对应Topic的分区。需要去导 spark-streaming-kafka-0-10_2.11的包。
如果是手动维护偏移量,那么进行一次判断,判断mysql表当中也就是历史数据是否存在偏移量,如果不存在偏移量说明spark程序是第一次启动那么就是按earliest进行消费,如果mysql当时存在偏移量的,那么spark程序至少启动过一次,那么会根据mysql偏移量进行消费,根据偏移量消费,需要封装一个HashMap[TopicPartition, Long],TopicPartition封装对应的topic名称和分区号,Long值就是对应的偏移量,然后将hashmap传入到ConsumerStrategies.Subscribe[String, String]这个方法的第三个参数里。

5.spark streaming如何访问jdbc连接

dstream.foreachRddd(rdd->{
rdd.foreachPartition(Partition->{
//在分区内创建jdbc连接
partition.foreach(item->{
//循环分区内每一条数据
//重复使用jdbc连接
}
//关闭jdbc资源,注意不关的话会造成内存泄露的问题呢
}
}

如果在spark程序遇到了object无法序列化的错误,那么需要注意代码里肯定是错误的将driver对象使用到了worker端。因为scala闭包特性,你在编写的时候是不会报错的。

6.spark streaming操作jdbc 线程安全问题

spark streaming程序是批处理数据,所以3秒一批数据,可能相同维度(可以是相同业务维度的数据,也可以是相同key的数据),然后mysql,多个分区内存在相同维度数据,
那么造成多线程同时去访问一个mysql资源,然后将mysql加载到自己的一个工作内存进行计算,再次刷写到mysql库当中,可能会存在线程安全问题,得到一个结果是不准确的,
那么解决办法
(1)加分布式锁 zookeeper redis 当然加了分布式锁之后速度会受到很大的影响 所以大数据情况不推荐使用
(2)groupby,groupbykey,reducebykey 这些算子将相同维度的数据聚合一个分区。进行操作之后那么一个分区它可能会有多个key的数据比如同时都有(用户id1001,1002的数据),1001和1002两个key的数据肯定是都是全部数据。所以说当一个key值的数据如果过多了那么进行join groupby reducebykey 操作都会造成一个数据倾斜的问题。

7.提交偏移量

dstream.froeachRdd(rdd->{

val offsetRanges: Array[OffsetRange] = rdd.asInstanceOf[HasOffsetRanges].offsetRanges
for (or <- offsetRanges) {
//可以获取topic名称 分区号 ,偏移量
or.topic, or.partition.toString, or.untilOffset
可以在for循环里去写sql语句将偏移量保存到mysql当中
}

如果偏移量想要手动维护并且提交到kafka,那么可以下面这个代码
stream.asInstanceOf[CanCommitOffsets].commitAsync(offsetRanges)

8.spark streaming程序在yarn一直运行着的

这个程序可能会挂掉的,并不是能完全一直运行下去的,那么这个时候需要比如第三方插件将spark streaming挂了之后重新拉起来。
重新拉起方法
(1)–supervise 官方提供的spark-submit参数
(2)supervise第三方一个插件,专门监控linux进程的一个守护进程,当你这个被监控进程如果挂掉了,那么这个supervise插件就会把你这个重新拉起来

9.spark streaming默认分区个数

默认分区个数是跟kafka分区个数挂钩,也就是kafka topic创建的时候指定了10个分区,那么spark stremaing默认一个分区就是10个,然后spark streaming一般不会去使用重分区的操作(把分区扩大或者分区缩小一般不会用),因为扩大repartition算子会造成 shuffle,shuffle数据会落盘那么会耗时,coalease算子缩小并行度就变小了速度就会变慢。

10.提交参数

spark sql当中task个数是cpu个数2倍到3倍,这个是离线数仓。
spark steaming当中要想spark streaming速度运行的最快,那么task运行比跟cpu必须1:1。1:1是最快的,让每个task同时并行的运行.所以集群当中数仓离线任务是耗内存任务,
实时任务是耗cpu的任务,如果你的公司分的细的那么两个集群分开,一个集群专门跑离线任务,一个集群跑实时任务。
spark-submit 控制cpu那么就是由 --num-executors --executor-cores 这两参数控制,也就是两个参数相乘要等于一个task个数的,task个数就是分区个数。而且如果cpu个数大于
task个数是没有效果的,会存在cpu空转的情况 。

你可能感兴趣的:(Spark,spark,数据仓库,大数据)