阿里云mapreduce Pipeline举例

阿里云的扩展MapReduce模型支持Map-Reduce-Reduce等复杂操作,减少了不必要的IO操作。在实际问题中,通过Pipeline模式解决了逻辑上的挑战,实现了map+2个reduce的运算流程。虽然文档对多个mapper的支持描述不清晰,但构建好pipeline对象并配置相关参数,就能实现所需的计算逻辑,推测中间可能借助shuffle优化了效率。
摘要由CSDN通过智能技术生成

在切入正题之前首先介绍下阿里云扩展的mapreduce。

传统的MapReduce模型要求每一轮MapReduce操作之后,数据必须落地到分布式文件系统上(比如HDFS或
ODPS表)。 而一般的MapReduce应用通常由多个MapReduce作业组成,每个作业结束之后需要写入磁盘
,接下去的Map任务很多情况下只是读一遍数据, 为后续的Shuffle阶段做准备,这样其实造成了冗余的IO操
作。
ODPS的计算调度逻辑可以支持更复杂编程模型, 针对上面的那种情况,可以在Reduce后面直接执行下一次的
Reduce操作,而不需要中间插入一个Map操作。 基于此,ODPS提供了扩展的MapReduce模型,即可以支持
Map后连接任意多个Reduce操作,比如Map-Reduce-Reduce。
Hadoop Chain Mappper/Reducer也支持类似的串行化Map或Reduce操作,但和ODPS的扩展
MapReduce(MR
2)模型有本质的区别, 因为Chain Mapper/Reducer还是基于传统的MapReduce模型,只是
可以在原有的Mapper或Reducer后面在增加一个或多个Mapper操作(不允许增加Reducer)。 这带来的好处是
用户可以复用之前的Mapper业务逻辑,可以把一个Map或Reduce拆成多个Mapper阶段,但本质上并没有改
变底层的调度和IO模型。

在实际应用中我遇到了一个比较棘手的问题,一开始觉得通过最简单的map和reduce两步操作在逻辑上就不太可行,后面使用pipeline模式完美的解决了该问题,话不多说直接上码!

package xxx.xxx

import java.io.IOException
import java.text.SimpleDateFormat
import com.aliyun.odps.data.{Record, TableInfo}
import com.aliyun.odps.mapred._
import com.aliyun.odps.pipeline.Pipeline
import com.aliyun.odps.Column
import com.aliyun.odps.OdpsType
import scala.collection.mutable.ArrayBuffer


/**
 * MapReduce Pipeline扩展<br/>
 * <p>
 * 在传统的MapReduce计算模型上做了扩展,可以在一轮Map/Reduce运算之后再加上一个或多个Reduce,
 * 即Map-Reduce-Reduce-Reduce...。一个Pipeline由多个节点顺序组成,每个节点是Mapper或Reducer<br/><br/>
 * 和普通的MapReduce一样,使用{@link Job}定义并提交作业,包括输入输入表的设置等。
 * 除此之外,还需要定义一个Pipeline对象(使用Pipeline.builder()方法),添加一个Mapper以及一个
 * 或多个Reducer。
 * <br/><br/>
 * 任何一个Mapper或处于中间状态的Reducer都需要显式定义输出结果的Key和Value的Schema定义
 * (定义方式类似于{@link JobConf#setMapOutputKeySchema(Column[])})。同时还可以设置
 * OutputKeySortColumns、PartitionColumns等。
  */

class LGTZMapper extends MapperBase {
  private var KEY: Record = _
  private var VALUE: Record = _
  val sdf = new SimpleDateFormat("yyyyMMddHHmmss")

  @throws[IOException]
  override def setup(context: Mapper.TaskContext)
  {
    KEY = context.createMapOutputKeyRecord
    VALUE = context.createMapOutputValueRecord
  }

  @throws[IOException]
  override def map(recordNum: Long, record: Record, context: Mapper.TaskContext)
  {
    def validateFunc(ValueArray: Array[String]): Boolean = {

      var isValid = false
      //0:xb_dm, 1:gmsfhm, 2:rzsj,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值