文件存储
分区规则: /houseId=?/dayId=?/hourId=?/minutet=5(5分钟产生一个文件)
存在问题:
1.收敛参数coalesce失效,小文件特别多
不同houseId(区域)的数据差异很大(如北上广与新疆西藏订单数据),导致清洗产生大量小文件
100G原始文件,清洗后产生10万多个文件
2.数据入库延迟大
因为kafka 不同分区流速差异大,HDFS数据有延迟几个小时,导致spark进行清洗后数据分布在多个时间分区,这也导致小文件
3.数据倾斜
不同houseId(省级区域)的数据差异很大,数据量从几兆到20G
数据倾斜,容易产生较慢的Task,拖累job执行时间,造成集群吞吐降低
4.清洗效率
小文件太多,直接导致NameNode压力过大(每个文件150Byte,一千万文件对应大概2G内存)负载过大,清洗效率非常慢
改造数据清洗流程:
1.数据入库效率改造
确保数据入HDFS延时不超过1小时
2.数据入HDFS目录,按照时间和house分目录: /${5分钟目录}/${houseId}
3.spark读取数据源目录,遍历5分钟目录的每个house目录
每个house目录生成一个DataFrame,根据每个house目录的大小确定收敛参数(coalesce)大小为partitionNum
根据性能考虑,将1小时内数据与1小时前的数据进行分开计算,为其分配合适的分区,提高计算效率,集群吞吐量
(1) 当前时间1小时的数据,转换为DataFrame ,分区书为partitionNum
(2) 过滤1小时前的数据,转换为DataFrame ,分区数大小为partitionNum的三分之一
4.使用union将每个目录生成的DataFrame合并一个DataFrame,将这个DataFrame写入分区
解决思路:
根据每个house目录的大小确定收敛参数(coalesce)大小解决了小文件文件(coalesce指定分区,可以避免产生过大小文件,不产生空文件),同时保证收敛后每个分区的数据基本均衡
Spark读取中文乱码:
spark textFile读取文件,但是该方法只支持UTF-8(面向传输的编码格式数据),不支持GBK(中文自负编码集),处理会产生乱码
sc.hadoopFile读取每个文件数据,处理数据单元
通过java new String(str,offset,str.length,charaSet)
spark json 解析文件都是面向传输效率高的UTF-8编码,不支持GBK,GB2312,GB18030
sc.hadoopFile同样进行数据单元处理,然后转换成RDD,然后进行sparkSession.read.json进行读取RDD
Spark Streaming监控文件目录开发,问题分析
1.无法解决小文件问题
2.spark streaming程序重启数据丢失
3.大文件入监控目录,入库时间长,spark streaming只会读取部分数据
生产不建议使用spark streaming监控文件,直接使用flume,filebeat ==> Kafka ===>spark streaming
Livy(CDH)进行spark任务发布,管理
优点:
1.交互式scala,Python,R,shell
2.多个提交scala,
3.多个用户可以共享一台server
4.可用于使用REST,从任何位置提交作业
5.不需要对程序进行任何代码修改,同spark-submit提交任务代码一样
6.亮点:共享sparkContext,RDDs(上一次计算的RDD结果,可以被下一个任务利用),避免重复计算,I/O
启动时:需要配置spark_home,hadoop_home
进行export 临时导入或者配置文件
spark 使用REST方式调用优点:
1.一个spark job值对应一个url,避免混淆
2.每个资源都是唯一标识,便于编程,抽象成统一API,避免重复开发
3.通过spark 调度引擎(livy,job server)可以共享sparkcontext,RDD,进而降低作业响应时间,提高集群工作效率,集群吞吐
4.便于进行程序,使用REST方式,每个资源对应一个URL标识,便于python,java,scala,shell程序开发,不会出现资源对应不一致,错误调用的情况
5.多任务提交不会出现冲突