一、链式MapReduce操作的概念
- 在以往的MapReduce案例中,无论是简单的WordCount还是比较复杂的使用MR统计社交共同好友的MapReduce作业都仅仅包含一个Map类和Reducer类,这就使得MR作业在实现某些复杂的程序时会遇到“有心无力”的尴尬问题。为此,Hadoop的MR有一个链式操作应运而生,所谓的链式操作一句话概括就是:在一个MapReduce作业中可以存在多个Map类,但是至多只能存在一个Reducer类,且可以在Reduce操作后继续执行Map操作。因此,通过合理地增加Map类可以使得MapReduce作业可以处理非常复杂的业务以及实现复杂的算法。
二、链式MapReduce实战案例
1. 需求分析
- 现在有这样一个场景:处理一批用户点击网页的日志,统计每一个网页被点击的次数,但是要过滤掉黑名单用户的点击数据,过滤完完对数据映射为KeyValue对并进行聚合操作,最后再过滤掉点击次数小于3次的点击统计信息。面对这样在一个场景可以使用链式操作完成:首先在第一个Map类中完成如下任务:加载HDFS中的黑名单数据进内存,取出用户的id与之一起存入Map集合中,然后把输入的点击日志的用户id与黑名单集合进行左外连接,若在黑名单集合中存在该用户则将该黑名单信息作为vale,key是点击网页的id;若用户不在黑名单集合里则value是字符串“NULL”,key还是点击网页的id。第二个Map的任务是过滤黑名单数据,只保留value是字符串“NULL的元组并将其映射为(页面id,1)。reduce操作将按key聚合得到各个网页的点击总数,reduce之后在进行一个Map过滤,将点击总数少于3的统计结果过滤掉,剩下的写入HDFS中。流程如下图:
2. 数据准备
- 点击日志clicklog.txt
20190612 1315 a1 20190612 2654 b1 20190612 1315 b2 20190612 2654 c3 20190612 2654 a1 20190612 7894 b2 20190612 7894 b2 20190612 1111 b2 20190612 1111 a1 20190612 1315 c3 20190612 1315 c3 20190612 1111 a1 20190612 7894 a1 20190612 7894 c3 20190612 7894 c3 20190612 1111 a1 20190612 2333 b2 20190612 2333 d4 20190612 2333 c3 20190612 2654 d4 20190612 1315 c3 20190612 2654 d4 20190612 1111 a1 20190612 1315 c3 20190612 1315 c3 20190612 1111 a1 20190612 7894 a1
- 黑名单数据blacklist.txt
1111 man 23 2333 man 21
- 将以上两份文件上传至HDFS
3. 代码编写
- 使用的Hadoop版本是 2.6.0-cdh5.7.0,开发工具是IEDA2018
- 构建Java工程引入完整依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.hadoop.train</groupId> <artifactId>hadooptrain</artifactId> <packaging>pom</packaging> <version>1.0</version> <name>hadooptrain</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> <hadoop.version>2.6.0-cdh5.7.0</hadoop.version> <zk.version>3.4.5-cdh5.7.0</zk.version> </properties> <repositories> <repository> <id>cloudera</id> <url>https://repository.cloudera.com/artifactory/cloudera-repos</url> </repository