Spark是一个通用的大规模数据快速处理引擎。可以简单理解为Spark就是一个大数据分布式处理框架。基于内存计算的Spark的计算速度要比Hadoop的MapReduce快上100倍以上,基于磁盘的计算速度也快于10倍以上。Spark运行在Hadoop第二代的yarn集群管理之上,可以轻松读取Hadoop的任何数据。能够读取HBase、HDFS等Hadoop的数据源。

从Spark 1.0版本起,Spark开始支持Spark SQL,它最主要的用途之一就是能够直接从Spark平台上面获取数据。并且Spark SQL提供比较流行的Parquet列式存储格式以及从Hive表中直接读取数据的支持。之后,Spark SQL还增加了对JSON等其他格式的支持。到了Spark 1.3 版本Spark还可以使用SQL的方式进行DataFrames的操作。我们通过JDBC的方式通过前台业务逻辑执行相关sql的增删改查,通过远程连接linux对文件进行导入处理,使项目能够初步支持Spark平台,现如今已支持Spark1.4版本。

SparkSQL具有内置的SQL扩展的基类实现Catalyst,提供了提供了解析(一个非常简单的用Scala语言编写的SQL解析器)、执行(Spark Planner,生成基于RDD的物理计划)和绑定(数据完全存放于内存中)。

前台我们使用ThriftServer连接后台SparkSQL,它是一个JDBC/ODBC接口,通过配置Hive-site.xml,就可以使前台用JDBC/ODBC连接ThriftServer来访问SparkSQL的数据。ThriftServer通过调用hive元数据信息找到表或文件信息在hdfs上的具体位置,并通过Spark的RDD实现了hive的接口。对于标签、客户群探索的增、删、改、查都是通过SparkSQL对HDFS上存储的相应表文件进行操作,突破了传统数据库的瓶颈,同时为以后的客户群智能分析作了铺垫。

1.数据的存储格式

我们使用Parquet面向列存存储的文件存储结构,因为Parquet具有高压缩比的特点且适合嵌套数据类型的存储,能够避免不必要的IO性能。Parquet建表如下所示:

CREATE TABLE dw_coclbl_d01_20140512_lzo_256_parquet(op_time string,

join_id double, city_id int, product_no string, brand_id int, vip_level int, county_id int, l2_01_01_04 double,  l2_01_01_04_01 double)

ROW FORMAT SERDE 'parquet.hive.serde.ParquetHiveSerDe'STORED AS

INPUTFORMAT 'parquet.hive.DeprecatedParquetInputFormat'

OUTPUTFORMAT 'parquet.hive.DeprecatedParquetOutputFormat';

2、由于压缩文件占用的空间较少,文件load的速度比较快。故使用压缩文件进行数据的load.使用gzip进行压缩时,单个文件只能在一个节点上进行load,加载时间很长。使用split命令将解压后的csv文件分割成多个256M的小文件,机器上每个block块的大小为128M,故将小文件分割为128M或256M以保证效率。由于Parquet存储格式暂时只支持Gzip,项目中暂时使用Gzip压缩格式。通过在控制台输入set mapreduce.output.fileoutputformat.compress=true指令命令设置压缩格式为true。再执行set mapreduce.output. fileoutput format.compress.codec = org.apache.hadoop.io.compress.GzipCodec;将文件的压缩格式设置为Gzip压缩格式

3、数据的导入。使用的是Apache的一个项目,最早作为Hadoop的一个第三方模块存在,主要功能是在Hadoop(hive)与传统的数据库(mysql、oracle等)间进行数据的传递,可以将一个关系型数据库中的数据导入到Hadoop的HDFS中,也可以将HDFS的数据导进到关系数据库中。

由于执行sqoop导入需要通过yarn的任务调度进行mapreduce,由于spark开启后即便在空闲状态下也不释放内存,故修改spark-env.sh配置,分配多余内存以便sqoop执行。

Create job -f 3 -t 4
Creating job for links with from id 3 and to id 4
    Please fill following values to create new job object
    Name: Sqoopy
    From database configuration
    Schema name: hive
    Table name: TBLS
    Table SQL statement: 
    Table column names: 
    Partition column name: 
    Null value allowed for the partition column: 
    Boundary query: 
    ToJob configuration
    Output format: 
      0 : TEXT_FILE
      1 : SEQUENCE_FILE
    Choose: 0
    Compression format: 
successfully created with validation status OK  and persistent id 2
     0 : NONE
      1 : DEFAULT
      2 : DEFLATE
      3 : GZIP
      4 : BZIP2
      5 : LZO
      6 : LZ4
      7 : SNAPPY
      8 : CUSTOM
    Choose: 0
    Custom compression format: 
    Output directory: hdfs://hadoop000:8020/sqoop2
    Throttling resources
    Extractors: 
    Loaders: 
    New job was

4、前台与后台交互工具类

工具类提供静态的方法,可以进行相应业务逻辑的调用,由于Hadoop集群存在于服务器端,前台需要实现跨平台服务器的连接,才能执行相应的Hadoop命令,实现对HDFS上文件的操作。此次设计的ShellUtils类,通过jsch连接Linux服务器执行shell命令.

private static JSch jsch;  
    private static Session session;  
    public static void connect(String user, String passwd, String host) throws JSchException {  
        jsch = new JSch();  
        session = jsch.getSession(user, host,22);  
        session.setPassword(passwd);  
        java.util.Properties config = new java.util.Properties();  
        config.put("StrictHostKeyChecking", "no");  
        session.setConfig(config);  

通过传入的Linux命令、用户名、密码等参数对远程linux服务器进行连接。由于执行Hadoop命令根据不同文件的大小所需占用的时间是不同的,在hadoop尚未将文件完全从hdfs上合并到本地时,本地会提前生成文件但文件内容为空,至此这里需要多传入前台客户群探索出来的客户群数目与文件条数进行对比,倘若数目相同则说明执行完毕。

CodecUtil类,用来实现不同类型压缩文件的解压工作,通过传入的压缩类型,利用反射机制锁定压缩的类型,由于存储在hdfs上的文件都是以文件块的形式存在的,所以首先需要获取hdfs中文件的二级子目录,遍历查询到每一个文件块的文件路径,随后通过输入输出流进行文件的解压工作。然后将此类打包成jar包放入集群中,通过前台远程连接服务端,执行hadoop命令操作执行,实现类部分代码如下:

public class CodecUtil{

public static void main(String[] args) throws Exception {

//compress("org.apache.hadoop.io.compress.GzipCodec");

String listName = args[0];

String codecType = args[1];

String hdfsPath = args[2];

uncompress(listName,codecType,hdfsPath);

//解压缩

public static void uncompress(String listName,String CodecType,String hdfsPath) throws Exception{

Class<?> codecClass = Class.forName(CodecType);

Configuration conf = new Configuration();

FileSystem fs = FileSystem.get(conf);

Path listf =new Path(hdfsPath+listName);

//获取根目录下的所有2级子文件目录

FileStatus stats[]=fs.listStatus(listf);

CompressionCodec codec = (CompressionCodec)

ReflectionUtils.newInstance(codecClass, conf);

int i;

for ( i = 0; i < stats.length; i++){

//获得子文件块的文件路径

String Random = findRandom();

Path list = new Path(stats[i].getPath().toString());

InputStream in = codec.createInputStream(inputStream);

FSDataOutputStream output = fs.create(new Path(hdfsPath + listName+"/"+unListName));

IOUtils.copyBytes(in, output, conf);

IOUtils.closeStream(in);

}

}

}

5、导入生成客户群

由于sparksql不支持insert into value语句,无法通过jdbc方式连接后台HDFS通过sparksql对文件进行导入数据的操作。于是将需要导入的csv文件通过ftp方式上传到远程服务器,再将文件通过load的方式导入表中,实现导入生成客户群的功能。

// 将文件上传到ftp服务器

CiFtpInfo ftp = customFileRelService.getCiFtpInfoByFtpType(1);

FtpUtil.ftp(ftp.getFtpServerIp(),ftp.getFtpPort(),ftp.getFtpUser(),DES.decrypt

(ftp.getFtpPwd()), ftpFileName, ftp.getFtpPath());

// 将文件load到表中

String ftpPath = ftp.getFtpPath();

if (!ftpPath.endsWith("/")) {

ftpPath = ftpPath + "/";

}

String sql = " LOAD DATA LOCAL INPATH '" + ftpPath + fileName

+ "' OVERWRITE INTO TABLE " + tabName;

log.info("loadSql=" + sql);

customersService.executeInBackDataBase(sql);

log.info("load table=" + tabName + " successful");

6、数据表或文件下载的实现

由于存储在hdfs上的数据为Gzip压缩格式,首先通过执行事先编好的解压代码对文件块进行解压,这里需要传入需要解压的文件名、解压类型、hdfs的完全路径,解压完毕后通过执行hadoop文件合并命令将文件从hdfs上合并到本地服务器,合并完毕后由于解压缩后的文件会占用hdfs的空间,同时执行hadoop文件删除命令将解压后的文件删除,再通过ftp传到前台服务器,完成客户群清单下载。

String command = "cd " + ftpPath + ";" + hadoopPath + "hadoop jar "+hadoopPath+"CodecTable.jar " + listRandomName +" "+ CodecType

+" " + " "+ hdfsWholePath + ";" + hadoopPath + "hadoop fs -cat '" +  hdfsPath + listRandomName + "/*'>" + listName1+".csv;" + hadoopPath +"hadoop fs -rm -r " + hdfsPath + listRandomName + ";" + "wc -l " + listName1 +".csv;";

LOG.debug(command);

flag = ShellUtils.execCmd(command, user, passwd, host,num);

清单的推送也是通过文件合并传输的方式进行其他平台的推送,大大降低了读取数据插入表数据所消耗的时间。

SparkSQL项目中的应用的更多相关文章

  1. VS项目中使用Nuget还原包后编译生产还一直报错?

    Nuget官网下载Nuget项目包的命令地址:https://www.nuget.org/packages 今天就遇到一个比较奇葩的问题,折腾了很久终于搞定了: 问题是这样的:我的解决方案原本是好好的 ...

  2. ABP项目中使用Swagger生成动态WebAPI

    本文是根据角落的白板报的<使用ABP实现SwaggerUI,生成动态webapi>一文的学习总结,感谢原文作者角落的白板报. 1 安装Swashbuckle.core 1.1 选择WebA ...

  3. iOS 之项目中遇到的问题总结

    昨天去一家公司面试,面试官问了我在项目开发中遇到过哪些问题,是什么引起的,怎样解决的? 当时由于有点小紧张只说出了一两点,现在就来好好总结一下. 问题: 1.两表联动 所谓的两表联动就是有左右两个表格 ...

  4. My97DatePicker时间控件在项目中的应用

    一.下载My97DatePicker的压缩包My97DatePicker.rar,解压. 注:My97DatePicker最新版本有开发包,项目中使用时删掉,以便节省空间,提高程序的运行效率. 二.在 ...

  5. 在项目中同时使用Objective-C和Swift

    苹果发布的Swift语言可以和之前的Objective-C语言同时存在于一个项目中. 可能有人会认为是同一个类文件中既可以有Objective-C也可以有Swift,这是不对的.同一个类文件或同一个代 ...

  6. 在数据库访问项目中使用微软企业库Enterprise Library,实现多种数据库的支持

    在我们开发很多项目中,数据访问都是必不可少的,有的需要访问Oracle.SQLServer.Mysql这些常规的数据库,也有可能访问SQLite.Access,或者一些我们可能不常用的PostgreS ...

  7. 在基于MVC的Web项目中使用Web API和直接连接两种方式混合式接入

    在我之前介绍的混合式开发框架中,其界面是基于Winform的实现方式,后台使用Web API.WCF服务以及直接连接数据库的几种方式混合式接入,在Web项目中我们也可以采用这种方式实现混合式的接入方式 ...

  8. Web API项目中使用Area对业务进行分类管理

    在之前开发的很多Web API项目中,为了方便以及快速开发,往往把整个Web API的控制器放在基目录的Controllers目录中,但随着业务越来越复杂,这样Controllers目录中的文件就增加 ...

  9. 如何决解项目中hibernate中多对多关系中对象转换json死循环

    先写一下原因吧!我是写的SSH项目,在项目中我遇到的问题是把分页对象(也就是pageBean对象)转化为json数据,下面为代码: public class PageBean <T>{// ...

随机推荐

  1. ctypes 模块

    ctypes赋予了python类似于C语言一样的底层操作能力,通过ctypes模块可以调用动态链接库中的导出函数.构建复杂的c数据类型. ctypes提供了三种不同的动态链接库加载方式:cdll(), ...

  2. JavaWeb学习记录(十五)——浏览器Cookie禁用后的处理

    IE禁用Cookie方式:

  3. Codeforces Round #148 (Div. 2)

    A. Two Bags of Potatoes 枚举倍数. B. Easy Tape Programming (待补) C. Not Wool Sequences 考虑前缀异或和. \[answer ...

  4. nginx下的rewrite

    一.正则表达式匹配,其中: * ~ 为区分大小写匹配 * ~* 为不区分大小写匹配 * !~和!~*分别为区分大小写不匹配及不区分大小写不匹配 二.文件及目录匹配,其中: * -f和!-f用来判断是否 ...

  5. Sublime Text 转

    距第一篇的开箱水文,已经有4个月的时间了,但因为懒,就没有下文了.终于,今天,我觉得写一篇准技术文章了. 忘记了是怎么开始用的ST,应该是在网上看到别人推荐才用到吧,用了有半年了.在windows下是 ...

  6. phpstorm用正则删除PHP代码空行小技巧

    有很多小伙伴会遇到代码空行特别多,但是一行一行删除肯定很烦躁,这时候就需要用到批量删除空行. 怎么批量删除空行呢? 我的办法是用正则把所有空行找到,然后一键全部替换. 首先把Match Case和Re ...

  7. 运用@media实现网页自适应中的几个关键分辨率

    http://jingyan.baidu.com/article/6f2f55a1ab36c3b5b83e6c46.html http://www.5imoban.net/jiaocheng/div+ ...

  8. 【转】 iOS日常学习 - iOS10上关于NSPhotoLibraryUsageDescription等问题

    原文网址:http://blog.csdn.net/wang631106979/article/details/52578001 最近升级了Xcode8.0,真是很多坑啊,填完一个来另外一个,今天又遇 ...

  9. CentOS 6 下RPM方式安装MySQL5.6

    CentOS 6 下RPM方式安装MySQL5.6 1. 下载Linux对应的RPM包,如:CentOS6.7_64对应的RPM包,如下:[root@mysql ~]# ll总用量 113808-rw ...

  10. 由浅入深探究mysql索引结构原理、性能分析与优化 转

    第一部分:基础知识 第二部分:MYISAM和INNODB索引结构 1. 简单介绍B-tree B+ tree树 2. MyisAM索引结构 3. Annode索引结构 4. MyisAM索引与Inno ...