分享

tez本地切分方式和AM端切分方式的区别

本帖最后由 helianthus 于 2016-4-4 13:30 编辑
问题导读:
1.tez的任务切分方式和MR有什么不同?
2.tez有哪些可选的切分方式?
3.不同的切分方式各有什么优缺点?为什么默认情况下选择在AM Container端切分?
4.切分相关的重要参数有哪些?




1.tez的应用场景:
      Tez被设计成一组lib库和APIs使得它能够更容易基于YARN做数据处理,它可以用于任何应用场景,只要应用逻辑最终的分布式结构是DAG形式就OK。TEZ本身并不提供任何逻辑处理的功能,但是它提供了一些基础模块使得应用程序可以更好地利用YARN进行资源调度、container分配、container启动等等,以及YARN运行报告(比如AST)以及安全管理等方面,这些都体现出tez和yarn之间的紧密联系。
       比起MR,tez提供了更灵活的选择空间:可以根据上游节点的处理结果数据动态调整需要的reduce个数,并且可以根据需要来决定将中间结果存放在内存还是磁盘。而tez和spark之前的比较可以说是没有什么可比性,因为它们本身就针对不同层次的两款产品,就好比要对苹果和橘子进行比较一样。因为比起spark所处的层次,tez属于较低级别的轻量级lib库和基础平台,而spark层次则更高些,它可以借助tez已经实现的某些功能模块来实现自己的逻辑。抽象到架构层面,甚至可以说spark应用可以架构在tez之上运行。2.tez session-mode和non-session mode:
        tezclient端用于提交待执行的DAGs,而DAGs的执行要通过Tez App Master实现。可以在TezClient以session或者Non-session方式运行App Master。
(1)在non-session模式下,每个DAG应用会在不同的App Master Container端执行,直到DAG执行完毕退出;
(2)在session模式下,tezClient会创建一个唯一的App Master实例,所有的DAGs都会提交给这一个App Master。
        session模式应该要比non-session模式在性能方面有更好的表现,因为session模式下所有的DAGs都可以对这个唯一的App master container实现资源重用。而Non-session模式更适合于只有一个DAG的情况或者想要多个没有关联的DGAs在提交到集群之后切断之间的联系等这类场景。可以通过修改session模式相关的配置来使得同一个应用程序序在session模式还是non-session模式执行。相关的配置可以在org.apache.tez.client.TezClient.java看到其逻辑实现。 tez1.png
tez session的使用步骤:
(1)实例化一个TezSession对象,其配置信息由TezSessionConfiguration提供;
(2)唤醒TezSession::start();
(3)等待tezSession准备好之后,通过TezSession::getSessionStatus()接口接入DAGs;
(4)通过TezSession::submitDAG(DAG dag)将一个DAGs提交到session;
(5)通过在(4)阶段实例化的DAGClient监控DAG的状态;
(6)一旦DAG执行完毕,对随后的DAGs只需要重复(4)和(5)步骤即可;
(7)当所有的工作完成,通过TezSession::stop()关闭session。

3.hive-on-tez数据切分方式:
   tez对数据的切分方式可以分为两种:
(1)本地切分,比如对于hive来说,本地切分就是在Hive Client端切分,在同一个JVM中进行数据切分,这种方式其实就是传统的MR切分方式;
(2)AM端切分,这种切分方式是在Job提交到YARN之后,在AMContainer中进行任务切分。    不同的切分方式可以通过tez提供的参数进行设置和选择,“hive.compute.splits.in.am”参数用于决定选择在client端切分还是在AM端切分。默认情况下,该参数的值为true,即默认DAG作业提交后,在AM端进行任务切分。
       在传统的MR模式下,在client端计算splits(一般在hiveclient端),此时还未申请资源运行。在这种方式下,作业的执行是顺序的,容易给该节点造成过重的并发负载,尤其在使用ODBC的时候。在AM端切分(hive.compute.splits.in.am=true)发生在tez job提交之后,也就是在集群AppMaster container中切分,这种方式提升了SQL执行效率。比如,多表join的情况下,选在AM端切分,只要有一个表完成了切分工作,就可以起task执行任务了,甚至可以等待第一个task执行完之后再执行后续的切分工作,这种方式甚至可以产生近乎1000x~以上的效率提升。
       关于两者的逻辑实现,选择在AM端切分时,用于生成splits的逻辑主要由org.apache.hadoop.hive.ql.exec.tez.HiveSplitGenerator实现。因为默认的输入格式是HiveInputFormat,因此,实际的切分会调用HiveinputFormat.getSplits()。如果hive.compute.splits.in.am=false,那么选择在Hive Client端切分,实际会调用MRInputHelpers.configureMRInputWithLegacySplitGeneration()进行实际的任务切分。关于任务切分的选择和实现,主要的入口逻辑是在创建并组装DAG的时候(DAGUtils),如下所示:
[mw_shl_code=java,true]    // remember mapping of plan to input
    conf.set(Utilities.INPUT_NAME, mapWork.getName());
    if (HiveConf.getBoolVar(conf, ConfVars.HIVE_AM_SPLIT_GENERATION)
        && !mapWork.isUseOneNullRowInputFormat()) {

      // set up the operator plan. (before setting up splits on the AM)
      Utilities.setMapWork(conf, mapWork, mrScratchDir, false);

      // if we're generating the splits in the AM, we just need to set
      // the correct plugin.
      if (groupSplitsInInputInitializer) {
        // Not setting a payload, since the MRInput payload is the same and can be accessed.
        InputInitializerDescriptor descriptor = InputInitializerDescriptor.create(
            HiveSplitGenerator.class.getName());
        dataSource = MRInputLegacy.createConfigBuilder(conf, inputFormatClass).groupSplits(true)
            .setCustomInitializerDescriptor(descriptor).build();
      } else {
        // Not HiveInputFormat, or a custom VertexManager will take care of grouping splits
        if (vertexHasCustomInput) {
          dataSource =
              MultiMRInput.createConfigBuilder(conf, inputFormatClass).groupSplits(false).build();
        } else {
          dataSource =
              MRInputLegacy.createConfigBuilder(conf, inputFormatClass).groupSplits(false).build();
        }
      }
    } else {
      // Setup client side split generation.
      dataSource = MRInputHelpers.configureMRInputWithLegacySplitGeneration(conf, new Path(tezDir,
          "split_" + mapWork.getName().replaceAll(" ", "_")), true);
      numTasks = dataSource.getNumberOfShards();

      // set up the operator plan. (after generating splits - that changes configs)
      Utilities.setMapWork(conf, mapWork, mrScratchDir, false);
    }
[/mw_shl_code]与hive-on-tez切分方式相关的参数主要有hive.compute.splits.in.am和hive.tez.input.generate.consistent.splits两个(暂时还未找到其他相关的参数);第二个参数表示是否要在切分split时是否保持切分信息与其location的一致性,默认true。
        tez还对切分后的实际的splits做了进一步的优化封装,可以将实际的splits按组分成逻辑上的更大的splits,涉及的主要实现类包括TezGroupedSplit和TezGroupedSplitsInputFormat。
4.关于hive-on-tez的个人学习方式小结
        通过从零开始学习tez,并将其应用到hive中,作为hive的执行引擎之一。这个全新的学习和应用过长中,从未知到入门到应用,我发现:
(1)首先搭建环境,把tez搭建起来,tez-on-yarn,所以,首先要能够在较浅的应用层面搭建好环境并做简单练习和应用;分析它的经典实例OrderedWordCount的实现,了解DAG是如何组装的,如何将用户自己的逻辑加进来;
(2)对于不知道的又无法查阅到相关权威资料的,直接看源码实现是最好的方式,跟进去DEBUG;
(3)对于源码中的某些实现不够理解的,发邮件到tez的邮件列表,请开发者给出权威踏实的解答,而不要道听途说在,自己猜测;
(4)持续关注社区动态,关注项目的JIRA单
(5)定期自我总结,自我归纳。
     通过以上几种方式可以比较好的了解和学习一门新技术。


已有(1)人评论

跳转到指定楼层
a530491093 发表于 2016-2-2 17:29:51
路过  顶你一贴!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条