HDAOOP SIMPLIZE TOOLKIT hadoop mapreduce简化开发包

https://github.com/jonenine/HST

 

虽然大数据的发展已经将近10个年头了,hadoop技术仍然没有过时,特别是一些低成本,入门级的小项目,使用hadoop还是蛮不错的。而且,也不是每一个公司都有能力招聘和培养自己的spark人才。

         我本人对于hadoop mapreduce是有一些意见的。hadoop mapreduce技术对于开发人员的友好度不高,程序难写,调试困难,对于复杂的业务逻辑远没有spark得心应手。

2016年的春节前接到一个任务,要在一个没有spark的平台实现电力系统的一些统计分析算法,可选的技术只有hadoop mapreduce。受了这个刺激之后产生了一些奇思妙想,然后做了一些试验,并最终形成HST---hadoop simplize toolkit,还真是无心载柳柳成荫啊。

 

HST基本优点如下:

屏蔽了hadoop数据类型,取消了driver,将mapperreducer转化为transformerjoiner,业务逻辑更接近sql。相当程度的减少了代码量,极大的降低了大数据编程的门槛,让基层程序员通过简单的学习即可掌握大数据的开发。

克服了hadoop mapreduce数据源单一的情况,比如在一个job内,input可以同时读文件和来自不同集群的hbase

远程日志系统,让mapperreducer的日志集中到driver的控制台,极大减轻了并行多进程程序的调试难度。

克服了hadoop mapreduce编写业务逻辑时,不容易区分数据来自哪个数据源的困难。接近了spark(或者sql)的水平。

天生的多线程执行,即在mapperreducer端都默认使用多线程来执行业务逻辑。

对于多次迭代的任务,相连的两个任务可以建立关联,下一个任务直接引用上一个任务的结果,使多次迭代任务的代码结构变得清晰优美。

 

以下会逐条说明

 

基本概念的小变化:

   Source类代替了hadoop Input体系(formatsplitreader)

   Transformer代替了mapper

   Joiner代替了Reducer

   去掉了饱受诟病的Driver,改为内置的实现,现在完全不用操心了。

                                                                          

<!--[if !supportLists]-->1.      <!--[endif]-->基本上,屏蔽了hadoop的数据类型,使用纯java类型

在原生的hadoop mapreduce开发中,使用org.apache.hadoop.io包下的各种hadoop数据类型,比如hadoopText类型,算法的编写中一些转换非常不方便。而在HST中一律使用java基本类型,完全屏蔽了hadoop类型体系。

比如在hbase作为sourceInput)的时候,再也不用直接使用ImmutableBytesWritableResult了,HST为你做了自动的转换。

现在的mapper(改名叫Transformer了)风格是这样的

publicstaticclass TransformerForHBase0 extends HBaseTransformer<Long>

现在map方法叫flatmap,看到没,已经帮你自动转成了stringmap

publicvoid flatMap(String key, Map<String, String> row,

           Collector<Long> collector)

 

可阅读xs.hadoop.iterated.IteratedUtil类中关于类型自动转换的部分

<!--[if !supportLists]-->2.      <!--[endif]-->克服了hadoop mapreduce数据源单一的情况。比如在一个job内,数据源同时读文件和hbase,这在原生的hadoop mapreduce是不可能做到的

 

以前访问hbase,需要使用org.apache.hadoop.hbase.client.ScanTableMapReduceUtil,现在完全改为与spark相似的方式。

现在的风格是这样的:

Configuration conf0 = HBaseConfiguration.create();

        conf0.set("hbase.zookeeper.property.clientPort", "2181");

        conf0.set("hbase.zookeeper.quorum", "172.16.144.132,172.16.144.134,172.16.144.136");

        conf0.set(TableInputFormat.INPUT_TABLE,"APPLICATION_JOBS");

        conf0.set(TableInputFormat.SCAN_COLUMN_FAMILY,"cf");

        conf0.set(TableInputFormat.SCAN_CACHEBLOCKS,"false");

conf0.set(TableInputFormat.SCAN_BATCHSIZE,"20000");

...其他hbaseConfiguration,可以来自不同集群。

 

IteratedJob<Long> iJob = scheduler.createJob("testJob")

                .from(Source.hBase(conf0), TransformerForHBase0.class)

              .from(Source.hBase(conf1), TransformerForHBase1.class)

               .from(Source.textFile("file:///home/cdh/0.txt"),Transformer0.class)

        .join(JoinerHBase.class)

 

Hadoop中的input,现在完全由source类来代替。通过内置的机制转化为inputformatinputsplitreader。在HST的框架下,其实可以很容易的写出诸如Source.dbms(),Source.kafka()以及Source.redis()方法。想想吧,在一个hadoop job中,你终于可以将任意数据源,例如来自不同集群的HBASE和来自数据库的source进行join了,这是多么happy的事情啊!

 

<!--[if !supportLists]-->3.      <!--[endif]-->远程日志系统。让mapperreducer的日志集中在driver进行显示,极大减轻了了并行多进程程序的调试难度

 

各位都体验过,job fail后到控制台页面,甚至ssh到计算节点去查看日志的痛苦了吧。对,hadoop原生的开发,调试很痛苦的呢!

现在好了,有远程日志系统,可以在调试时将mapperreducer的日志集中在driver上,错误和各种counter也会自动发送到driver上,并实时显示在你的控制台上。如果在eclipse中调试程序,就可以实现点击console中的错误,直接跳到错误代码行的功能喽!

Ps:有人可能会问,如何在集群外使用eclipse调试一个job,却可以以集群方式运行呢?这里不再赘述了,网上有很多答案的哦

 

<!--[if !supportLists]-->4.      <!--[endif]-->克服了hadoop mapreducejoin上,区分数据来自哪个数据源的困难,接近spark(或者sql)的水平

在上面给出示例中,大家都看到了,现在的mapper可以绑定input喽!,也就是每个input都有自己独立的mapper。正因为此,现在的inputmapper改名叫SourceTransformer

那么,大家又要问了,在mapper中,我已经可以轻松根据不同的数据输入写出不同的mapper了,那reducer中怎么办,sparksql都是很容易实现的哦?比如看人家sql

Select a.id,b.name from A  a,B  b where a.id = b.id

多么轻松愉悦啊!

在原生hadoop mapreduce中,在reducer中找出哪个数据对应来自哪个input可是一个令人抓狂的问题呢!

现在这个问题已经被轻松解决喽!看下面这个joiner,对应原生的reducer

publicstaticclass Joiner0 extends Joiner<Long, String, String>

Reduce方法改名叫join方法,是不是更贴近sql的概念呢?

        publicvoid join(Long key,RowHandler handler,Collector collector) throws Exception{

                List<Object> row  = handler.getSingleFieldRows(0);//对应索引为0source

         List<Object> row2 = handler.getSingleFieldRows(1);//对应第二个定义的source

注意上面两句,可以按照数据源定义的索引来取出来自不同数据源join后的数据了,以后有时间可能会改成按照别名来取出,大家看源码的时候,会发现别名这个部分的接口都写好了,要不你来帮助实现了吧。

 

<!--[if !supportLists]-->5.      <!--[endif]-->天生的多线程执行,即在mapperreducer端都默认使用多线程来执行业务逻辑。

    看看源码吧,HST框架是并发调用flatMapjoin方法的,同时又不能改变系统调用reduce方法的顺序(否则hadoop的辛苦排序可就白瞎了),这可不是一件容易的事呢!

看到这里,有的同学说了。你这个HST好是好,但你搞的自动转换类型这个机制可能会把性能拉下来的。这个吗,不得不承认,可能是会有一点影响。但在生产环境做的比对可以证明,影响太小了,基本忽略不计。

笔者在生产环境做了做了多次试验,mapper改成多线程后性能并未有提高,特别是对一些业务简单的job,增加Transformer中的并发级别效率可能还会下降。

很多同学喜欢在mapper中做所谓“mapper端的join”。这种方式,相信在HST中通过提高mapper的并发级别后会有更好的表现。

Reducer中的性能相对原生提升的空间还是蛮大的。大部分的mapreduce项目,都是mapper简单而reducer复杂,HST采用并发执行join的方式对提升reducer性能是超好的。

 

<!--[if !supportLists]-->6.      <!--[endif]-->对于多次迭代的任务,相连的两个任务可以建立关联,在流程上的下一个job直接引用上一个job的结果,使多次迭代任务的代码结构变得清晰优美

虽然在最后才提到这一点,但这却是我一开始想要写HST原因。多次迭代的任务太麻烦了,上一个任务要写在hdfs做存储,下一个任务再取出使用,麻烦不麻烦。如果都由程序自动完成,岂不美哉!

在上一个任务里format一下

IteratedJob<Long> iJob = scheduler.createJob("testJob")

...//各种source定义

.format("f1","f2")

在第二个任务中,直接引用

IteratedJob<Long> stage2Job = scheduler.createJob("stage2Job")

.fromPrevious(iJob, Transformer2_0.class);

                  //Transformer2_0.class

 

       publicstaticclass Transformer2_0 extends PreviousResultTransformer<Long>

       ...

           publicvoid flatMap(Long inputKey, String[] inputValues,Collector<Long> collector) {

           String f1 = getFiledValue(inputValues, "f1");

           String f2 = getFiledValue(inputValues, "f2");

    看到没,就是这么简单。

在最开始的计划中,我还设计了使用redis队列来缓冲前面job的结果,供后面的job作为输入。这样本来必须严格串行的job可以在一定程度上并发。另外还设计了子任务的并发调度,这都留给以后去实现吧。

 

<!--[if !supportLists]-->7.  <!--[endif]-->便捷的自定义参数传递。

有时候,在业务中需要作一些“开关变量”,在运行时动态传入不同的值以实现不同的业务逻辑。这个问题HST框架其实也为你考虑到了。

Driver中的自定义参数,source中的自定义参数都会以内置的方式传到transformerjoiner中去,方便程序员书写业务。

   查看transformerjoiner的源码就会发现:

getSourceParam(name)getDriverParam(pIndex)方法,在计算节点轻松的得到在driversource中设置的各层次级别的自定义参数,爽吧!

 

<!--[if !supportLists]-->8.  <!--[endif]-->其他工具

 

HST提供的方便还不止以上这些,比如在工具类中还提供了两行数据(map类型)直接join的方法。这些都留给你自己去发现并实践吧!

https://github.com/jonenine/HST

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于微信小程序的家政服务预约系统采用PHP语言和微信小程序技术,数据库采用Mysql,运行软件为微信开发者工具。本系统实现了管理员和客户、员工三个角色的功能。管理员的功能为客户管理、员工管理、家政服务管理、服务预约管理、员工风采管理、客户需求管理、接单管理等。客户的功能为查看家政服务进行预约和发布自己的需求以及管理预约信息和接单信息等。员工可以查看预约信息和进行接单。本系统实现了网上预约家政服务的流程化管理,可以帮助工作人员的管理工作和帮助客户查询家政服务的相关信息,改变了客户找家政服务的方式,提高了预约家政服务的效率。 本系统是针对网上预约家政服务开发的工作管理系统,包括到所有的工作内容。可以使网上预约家政服务的工作合理化和流程化。本系统包括手机端设计和电脑端设计,有界面和数据库。本系统的使用角色分为管理员和客户、员工三个身份。管理员可以管理系统里的所有信息。员工可以发布服务信息和查询客户的需求进行接单。客户可以发布需求和预约家政服务以及管理预约信息、接单信息。 本功能可以实现家政服务信息的查询和删除,管理员添加家政服务信息功能填写正确的信息就可以实现家政服务信息的添加,点击家政服务信息管理功能可以看到基于微信小程序的家政服务预约系统里所有家政服务的信息,在添加家政服务信息的界面里需要填写标题信息,当信息填写不正确就会造成家政服务信息添加失败。员工风采信息可以使客户更好的了解员工。员工风采信息管理的流程为,管理员点击员工风采信息管理功能,查看员工风采信息,点击员工风采信息添加功能,输入员工风采信息然后点击提交按钮就可以完成员工风采信息的添加。客户需求信息关系着客户的家政服务预约,管理员可以查询和修改客户需求信息,还可以查看客户需求的添加时间。接单信息属于本系统里的核心数据,管理员可以对接单的信息进行查询。本功能设计的目的可以使家政服务进行及时的安排。管理员可以查询员工信息,可以进行修改删除。 客户可以查看自己的预约和修改自己的资料并发布需求以及管理接单信息等。 在首页里可以看到管理员添加和管理的信息,客户可以在首页里进行家政服务的预约和公司介绍信息的了解。 员工可以查询客户需求进行接单以及管理家政服务信息和留言信息、收藏信息等。
数字社区解决方案是一套综合性的系统,旨在通过新基建实现社区的数字化转型,打通智慧城市建设的"最后一公里"。该方案以国家政策为背景,响应了国务院、公安部和中央政法会议的号召,强调了社会治安防控体系的建设以及社区治理创新的重要性。 该方案的建设标准由中央综治办牵头,采用"9+X"模式,通过信息采集、案(事)件流转等手段,实现五级信息中心的互联互通,提升综治工作的可预见性、精确性和高效性。然而,当前社区面临信息化管理手段不足、安全隐患、人员动向难以掌握和数据资源融合难等问题。 为了解决这些问题,数字社区建设目标提出了"通-治-服"的治理理念,通过街道社区、区政府、公安部门和居民的共同努力,实现社区的平安、幸福和便捷。建设思路围绕"3+N"模式,即人工智能、物联网和数据资源,结合态势感知、业务分析和指挥调度,构建起一个全面的数据支持系统。 数字社区的治理体系通过"一张图"实现社区内各维度的综合态势可视化,"一套表"进行业务分析,"一张网"完成指挥调度。这些工具共同提升了社区治理的智能化和效率。同时,数字社区还提供了包括智慧通行、智慧环保、居家养老和便民服务等在内的多样化数字服务,旨在提升居民的生活质量。 在硬件方面,数字社区拥有IOT物联网边缘网关盒子和AI边缘分析盒子,这些设备能够快速集成老旧小区的物联设备,实现传统摄像设备的智能化改造。平台优势体现在数字化能力中台和多样化的应用,支持云、边、端的协同工作,实现模块化集成。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值