在上一章节 我们讲到了hbase的使用回顾, 这一章我们将一下同样是nosql的另一分支 mongodb 基于文档型数据库
mongodb的基本使用 下面是一张与oracle mysql这种关系型数据库的对比
基本操作 crud
db.users.insert( { user_id: "abc123", age: 55, status: "A" } ) db.users.update( { }, { $set/$unset: { join_date: new Date() } }, { multi: true } ) db.users.drop() 查找全部 db.users.find(); 查找通过statu=a 查找该列 0 代表 不查找该列 1代表查找该列 db.users.find( { status: "A" }, { user_id: 1, status: 1, _id: 0 } ) 相当于 SELECT user_id, status FROM users WHERE status = "A" 还有好多 like 查询 count统计查询 group by等等 mongodb也是支持的
详细使用见官方文档,这里只是先温习加mongodb基本使用,我们本节的重点是怎么整合mongodb与hadoop
mongodb官方 有一个开源项目 mongodb-hadoop该项目是使mongodb能作为hadoop数据库
这样 你就可以某种情况下可以替代hbase cassicade了
pom文件加入相关依赖
org.mongodb mongo-hadoop 1.0.0 org.mongodb mongo-hadoop-core 1.1.0 org.apache.hadoop hadoop-core 0.20.2
同时还要加上mongod连接java的驱动
org.mongodb mongo-java-driver 2.11.2
这里上面的图涉及到了PIG pig本来我想介绍下,发现网络上有几篇非常好的文章
这里我就不献丑了
地址
转文章来源:http://www.codelast.com/
(1)《Apache Pig的一些基础概念及用法总结(1)》
(2)《Apache Pig的一些基础概念及用法总结(2)》
(3)《Apache Pig中文教程(进阶)》
(4)《使用Apache Pig时应该注意/避免的操作或事项》
这里不详细介绍了 还有个HIVE IMPALA 以后有时间会讲下
很多时候 我们是用sqoop相关工具 把关系型数据库导入到相关Hbase数据库 而导入mongodb 的话网上应该有好多工具导入,以及自带的命令mongoexport 同oracle一样sqlldr 。。。等
上面说到mongodb 官方提供的mongodb-hadoop用于mongodb与hadoop进行整合
上篇文章http://my.oschina.net/yilian/blog/175525 讲到了DBobject这个对象 他代表的mongodb的一个document 的每一行存的BJSON类型 的java对象 可以看成key-value形式
正常的时候 我们知道mongodb 数据库是提供一个mapreduce方法调用
使用方法类似
JSONObject json = null; DBObject query = new BasicDBObject(); String mapper = "function(){ emit( this.name,this.money); }"; String reduce = "function(key, values){ var count=0; for(var i in values){ count+=values[i]; } return {'name':key,'money':count};}"; MapReduceOutput out = getCollection().mapReduce( mapper , reduce , "" + System.currentTimeMillis() , query ); DBCursor cur = out.getOutputCollection().find(); while ( cur.hasNext() ) { query = cur.next(); json = JSONObject.fromObject( query ); } out.drop();
这里注意 几个参数 对于为什么这么写 怎么写mapreduce?请参考官方的文档 地址,以及后面附件的图片
http://docs.mongodb.org/manual/reference/command/mapReduce/#dbcmd.mapReduce
/** * performs a map reduce operation * Runs the command in REPLACE output mode (saves to named collection) * * @param map * map function in javascript code * @param outputTarget * optional - leave null if want to use temp collection * @param reduce * reduce function in javascript code * @param query * to match * @return * @throws MongoException * @dochub mapreduce */ public MapReduceOutput mapReduce( String map , String reduce , String outputTarget , DBObject query ){ return mapReduce( new MapReduceCommand( this , map , reduce , outputTarget , MapReduceCommand.OutputType.REPLACE, query ) ); }
在hadoop中 我们使用monodb作为数据源 读入 进行 mapreduce 处理后 写入,在第一章我们讲到了对于自定义只要实现相应的InputFormat 以及Recorder即可,同样mongodb-hadoop 提供了 相应的实现,他允许使用mongodb(或者是使用BSON作为格式的备份文件)作为hadoop MapReduce的输入源和输出源
这里先说下Mongo-Hadoop的工作流程:
1) Mongo-Hadoop首先检查MongoDB Collection,并计算数据分割
2) 每个分割部分被分配到Hadoop集群中的一个节点
3) 同时,Hadoop节点从MongoDB(或BSON)获取数据,并进行本地处理
4) Hadoop合并结果,并输出到MongoDB或BSON
下面来介绍怎么使用,正常时候实现mapper时候 只要继承mapper类 然后
这里BSON就是下面我们mapper reduce的关键了 下面是一个mapper实现
public class MyMapper extends Mapper
同理reduce也是类似写法,注意BsonObject就可以了 此外注意的是BSONWritable
public class MyReducer extends Reducer{ @Override public void reduce( final IntWritable key, final Iterable values, final Context context ) throws Exception{ //..... BasicBSONObject output = new BasicBSONObject(); output.put("name", name); context.write( key, new BSONWritable( output ) ); } }
下面就是继承Configred 实现Tool 来编写一个JOB 这里要注意的是mongodb参数输入地址 输出地址是
mongodb://地址:端口/collection
还要设置一些属性 这是官方实例中的一段
job.setReducerClass(MongoConfigUtil.getReducer(conf)); job.setMapperClass(MongoConfigUtil.getMapper(conf)); job.setOutputFormatClass(MongoConfigUtil.getOutputFormat(conf)); job.setOutputKeyClass(MongoConfigUtil.getOutputKey(conf)); job.setMapOutputKeyClass(MongoConfigUtil.getMapperOutputKey(conf)); job.setMapOutputValueClass(MongoConfigUtil.getMapperOutputValue(conf)); job.setInputFormatClass(MongoConfigUtil.getInputFormat(conf));
也就是说 他把config文件中的配置属性转换成相应的
public static Class extends OutputFormat> getOutputFormat( Configuration conf ){ return conf.getClass( JOB_OUTPUT_FORMAT, null, OutputFormat.class ); }
而getClass就是反射。。很简单吧,其实就是设置InputFormatClass类为 com.mongodb.hadoop.MongoInputFormat outFormatClass类为com.mongodb.hadoop.MongooutputFormat 然后设置mapper类 reduce类为相应的mapper reduce 这里他这样做是使者job工作交给xml配置好,减少job配置 ,采用xml配置,读取xml反射 注入
实际上mongodb-hadoop还提供了一个mongoTool 工具定义好了相应的,只需你配置好xml文件 该类注释上有很详细的使用方法
/** * Tool for simplifying the setup and usage of Mongo Hadoop jobs using the Tool / Configured interfaces for use w/ a * ToolRunner Primarily useful in cases of XML Config files. * * @author Brendan W. McAdams*/ public class MongoTool extends Configured implements Tool { private static final Log log = LogFactory.getLog( MongoTool.class ); public int run( String[] args ) throws Exception{ /** * ToolRunner will configure/process/setup the config * so we need to grab the classlevel one * This will be inited with any loaded xml files or -D prop=value params */ final Configuration conf = getConf(); final Job job = new Job( conf, _jobName ); /** * Any arguments specified with -D = * on the CLI will be picked up and set here * They override any XML level values * Note that -D is important - no space will * not work as it get spicked up by Java itself */ // TODO - Do we need to set job name somehow more specifically? // This may or may not be correct/sane job.setJarByClass( this.getClass() ); final Class mapper = MongoConfigUtil.getMapper( conf ); log.info( "Mapper Class: " + mapper ); job.setMapperClass( mapper ); Class extends Reducer> combiner = MongoConfigUtil.getCombiner(conf); if (combiner != null) { job.setCombinerClass( combiner ); } job.setReducerClass( MongoConfigUtil.getReducer( conf ) ); job.setOutputFormatClass( MongoConfigUtil.getOutputFormat( conf ) ); job.setOutputKeyClass( MongoConfigUtil.getOutputKey( conf ) ); job.setOutputValueClass( MongoConfigUtil.getOutputValue( conf ) ); job.setInputFormatClass( MongoConfigUtil.getInputFormat( conf ) ); Class mapOutputKeyClass = MongoConfigUtil.getMapperOutputKey(conf); Class mapOutputValueClass = MongoConfigUtil.getMapperOutputValue(conf); if(mapOutputKeyClass != null){ job.setMapOutputValueClass(mapOutputKeyClass); } if(mapOutputValueClass != null){ job.setMapOutputValueClass(mapOutputValueClass); } /** * Determines if the job will run verbosely e.g. print debug output * Only works with foreground jobs */ final boolean verbose = MongoConfigUtil.isJobVerbose( conf ); /** * Run job in foreground aka wait for completion or background? */ final boolean background = MongoConfigUtil.isJobBackground( conf ); try { if ( background ){ log.info( "Setting up and running MapReduce job in background." ); job.submit(); return 0; } else{ log.info( "Setting up and running MapReduce job in foreground, will wait for results. {Verbose? " + verbose + "}" ); return job.waitForCompletion( true ) ? 0 : 1; } } catch ( final Exception e ) { log.error( "Exception while executing job... ", e ); return 1; } } /** * Main will be a necessary method to run the job - suggested implementation * template: 这是使用方法 * public static void main(String[] args) throws Exception { * int exitCode = ToolRunner.run(new (), args); * System.exit(exitCode); * } * */ /** * SET ME Defines the name of the job on the cluster. Left non-final to allow tweaking with serial #s, etc */ String _jobName = " "; }
这个类 你可以继承 重载,也可以直接使用,常用的一个xml配置文件 我在官方实例中找的 ,去掉一些不必要的东西
mongo.job.verbose true mongo.job.background false mongo.input.key mongo.input.uri mongodb://localhost:27017/basetest.videoAttachments mongo.output.uri mongodb://localhost:27017/basetest.videoMapReduceResult mongo.input.query mongo.input.fields mongo.input.sort mongo.input.limit 0 mongo.input.skip 0 mongo.job.mapper ru.switchsocial.hadoop.SimpleMapper mongo.job.reducer ru.switchsocial.hadoop.SimpleReducer mongo.job.input.format com.mongodb.hadoop.MongoInputFormat mongo.job.output.format com.mongodb.hadoop.MongoOutputFormat mongo.job.output.key org.apache.hadoop.io.IntWritable mongo.job.output.value com.mongodb.hadoop.io.BSONWritable mongo.job.mapper.output.key org.apache.hadoop.io.IntWritable mongo.job.mapper.output.value org.apache.hadoop.io.IntWritable mongo.job.partitioner mongo.job.sort_comparator
这里注意的是 上面的配置 我修改成我自己的后运行后发现爆出了calculate input splits: need to login错误
http://stackoverflow.com/questions/16916146/hadoop-error-unable-to-calculate-input-splits-need-to-login/16925434#16925434 这上面提出了解决方案
只要加上conf.setBoolean(“mongo.input.split.create_input_splits”, false); 即可
为什么需要这样呢?我查找了官方文档发现了这么一段话
也就是说 共享 与 非共享collections 的处理的true false问题
这里还有个问题,有可能会提示找不到xxx错误,其实只要把mongodb-hadoop复制到hadoop 的lib目录下 或者hadoop add jar命令也可以即可
下面大家就可以拿官方examples文件去按照上述去运行了。。
在这里我要提的是mongodb 其实提供了group by sort aggregation 等一些函数 aggregation其实也是mapreduce的优化实现 这里希望大家去看看也就是说,上面的其实可以直接通过他实现
详细文档地址http://docs.mongodb.org/manual/applications/aggregation/
另外附录几张 图片帮助理解
这里要说的是mongodb可作为hadoop storm spark s3的数据源还是不错的,stackoverflow上面有些与hbase cassisade对比的帖子,关键是 他可以从hdfs 可以从关系数据库到 可以从hbase 等等导入导出
这篇文章是本人抽出时间 多次修改草稿编写的,也许有些不衔接的 请见谅,在找工作中!没多少时间更新,几天才出这篇,最近也在研究apache mohout 这个数据挖掘 推荐算法 分析 的东西,下一章 有可能会更新impala 这个比hive高效的查询框架,hive会稍微提下,有什么问题可以在下面留言回复,本人项目一直在cloudra的伪分布式运行。。关于cloudra这个网站的的工具 ,很方便安装hadoop的各种环境,大家百度搜索就有好多相关文档教程,,以前有个hadoop4win只能安装基本环境,而cloudra很方便,其实impala也是这个公司开源的一个框架
还有就是 我没有讲到sping-hadoop这项目的任何东西,其实前面的知识只是基础,后面讲完了体系后,会讲hbaseTemplate pigTemplate hiveTemplate…等等很方便处理hadoop的常用操作,统一讲一下源代码怎么实现,以及他的回调机制
声明:OSCHINA 博客文章版权属于作者,受法律保护。未经作者同意不得转载。
本文转载于:文章来自KENGINE | Kankanews.com