学习hadoop对cpu要求高吗

一、对于CDH的小总结:
& & & CDH:是Cloudera公司在Apache开源项目hadoop的基础上发型的,共有五个版本前两个已不再更新,最经的两个分别是CDH4(基于hadoop2.0.0版本演化而来)、CDH5(每隔一段时间就会有更新)
CDH与Apache hadoop的区别:1.CDH的版本更加清晰,现在只有两个版本CDH3(基于hadoop1.0)和CDH4(基于hadoop2.0),hadoop的版本相对较混乱,CDH比Apache hadoop在兼容性、安全性、稳定性上有所增强;
2.CDH在hadoop基础上加入了很多的Patch和修复了BUG,更新速度比hadoop要快。
3.安全,CDH支持kerberos安全认证,Apache hadoop只支持简单的用户名匹配认证。
4.CDH的安装方式有四种:YUM/Apt包、Tar包、RPM包、Cloudera Manager而Apache hadoop只支持Tar安装。
二、SecondaryNameNode的作用:
& & &1.SecondaryNameNode是一个NameNode的快照,它会定期的根据配置:fs.checkpoint.period,默认值是3600秒,去查看备份NameNode节点上的fsimage镜像文件和edits日志文件,并定期对这两个文件进行合并,将edits文件的控制在一定的大小限度内。fs.checkpoint.size:设置了edits文件的大小,默认是64M,一旦edits大于这个值的时候回强制执行检查点。
& & &2.SecondaryNameNode作为一个检查点会保存最新的检查点的目录结构信息与NameNode上的目录结构信息是一致的,以前的fsimage和的edits会自动丢失。
& & &3.当NameNode意外挂掉的时候,需要人为手动的将SecondaryNameNode检查点的信息复制到NameNode节点:具体操作如下:
& & &前提:目录已经丢失& & &a.把SecondaryNameNode节点中 ${fs.checkpoint.dir} 的所有内容拷贝到NameNode节点的 ${fs.checkpoint.dir} 目录中& & &b.创建一个空的文件夹dfs.namenode.name.dir所指向的文件夹;& & &c.启动NameNode:hadoop namenode -importCkeckpoint
(该步会从${fs.checkpoint.dir}中恢复到${dfs.namenode.name.dir}中,并启动namenode)
三、根据Yarn的架构描述一下一个资源的请求流程:
& & &1.Nodemanager向ResourceManager注册各个机器的资源;& & &2.客户端Client向ResourceManager提交作业;& & &3.ApplicationMaster(位于其中的一个NodeManager上)向ResourceManager请求资源,并判断NodeManager上现有的资源是否满足需求;& & &4.ResourceManager以Container的形式将资源发送给ApplicationMaster;& & &5.ApplicationMaster将得到的资源分发给NodeManager,各个NodeManager根据Container,启动一定数量的Task运行作业;& & &6.Container(包含了CPU,硬盘,环境配置,启动命令等信息)作为资源单元保证了作业的隔离运行。& & &7.各个Task定期的通过心跳机制给ApplicationMaster汇报任务的完成状况。最终直至任务完成,ApplicaMaster将完成信息返回给ResourceManager。
如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】。
如果,您希望更容易地发现我的新博客,不妨点击一下左下角的【关注我】。
如果,您对我的博客所讲述的内容有兴趣,请继续关注我的后续博客,我是【】,谢谢!
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
阅读(...) 评论()每天发现一点点!
当前位置: >
hadoop面试经历
篇一:Hadoop面试题目及答案 Hadoop面试45个题目及答案 1.Hadoop集群可以运行的3个模式? 单机(本地)模式 伪分布式模式 全分布式模式 2.
单机(本地)模式中的注意点? 在单机模式(standalone)中不会存在守护进程,所有东西都运行在一个JVM上。这里同样没有DFS,使用的是本地文件系统。单机模式适用于开发过程中运行MapReduce程序,这也是最少使用的一个模式。 3.
伪分布模式中的注意点? 伪分布式(Pseudo)适用于开发和测试环境,在这个模式中,所有守护进程都在同一台机器上运行。 4.
VM是否可以称为Pseudo? 不是,两个事物,同时Pseudo只针对Hadoop。 5.
全分布模式又有什么注意点? 全分布模式通常被用于生产环境,这里我们使用N台主机组成一个Hadoop集群,Hadoop守护进程运行在每台主机之上。这里会存在Namenode运行的主机,Datanode运行的主机,以及task tracker运行的主机。在分布式环境下,主节点和从节点会分开。 6.
Hadoop是否遵循UNIX模式? 是的,在UNIX用例下,Hadoop还拥有“conf”目录。 7.
Hadoop安装在什么目录下?Cloudera和Apache使用相同的目录结构,Hadoop被安装在cd/usr/lib/hadoop-0.20/。 8.
Namenode、Job tracker和task tracker的端口号是? Namenode,70;Job tracker,30;Task tracker,60。 9.
Hadoop的核心配置是什么? Hadoop的核心配置通过两个xml文件来完成:1,hadoop-default.xml;2,hadoop-site.xml。这些文件都使用xml格式,因此每个xml中都有一些属性,包括名称和值,但是当下这些文件都已不复存在。 10.
那当下又该如何配置? Hadoop现在拥有3个配置文件:1,core-site.xml;2,hdfs-site.xml;3,mapred-site.xml。这些文件都保存在conf/子目录下。 11.
RAM的溢出因子是? 溢出因子(Spill factor)是临时文件中储存文件的大小,也就是Hadoop-temp目录。 12.
fs.mapr.working.dir只是单一的目录? fs.mapr.working.dir只是一个目录。 13.
hdfs-site.xml的3个主要属性? dfs.name.dir决定的是元数据存储的路径以及DFS的存储方式(磁盘或是远端) dfs.data.dir决定的是数据存储的路径 fs.checkpoint.dir用于第二Namenode 14.
如何退出输入模式? 退出输入的方式有:1,按ESC;2,键入:q(如果你没有输入任何当下)或者键入:wq(如果你已经输入当下),并且按下Enter。15.
当你输入hadoopfsck /造成“connection refused java exception’”时,系统究竟发生了什么? 这意味着Namenode没有运行在你的VM之上。 16.
我们使用Ubuntu及Cloudera,那么我们该去哪里下载Hadoop,或者是默认就与Ubuntu一起安装? 这个属于Hadoop的默认配置,你必须从Cloudera或者Edureka的dropbox下载,然后在你的系统上运行。当然,你也可以自己配置,但是你需要一个Linux box,Ubuntu或者是Red Hat。在Cloudera网站或者是Edureka的Dropbox中有安装步骤。 17.
“jps”命令的用处? 这个命令可以检查Namenode、Datanode、Task Tracker、 Job Tracker是否正常工作。 18.
如何重启Namenode? 点击stop-all.sh,再点击start-all.sh。 键入sudo hdfs(Enter),su-hdfs (Enter),/etc/init.d/ha(Enter),及/etc/init.d/hadoop-0.20-namenode start(Enter)。 19.
Fsck的全名? 全名是:File System Check。 20.
如何检查Namenode是否正常运行? 如果要检查Namenode是否正常工作,使用命令/etc/init.d/hadoop-0.20-namenode status或者就是简单的jps。 21.
mapred.job.tracker命令的作用? 可以让你知道哪个节点是Job Tracker。22.
/etc /init.d命令的作用是? /etc /init.d说明了守护进程(服务)的位置或状态,其实是LINUX特性,和Hadoop关系不大。 23.
如何在浏览器中查找Namenode? 如果你确实需要在浏览器中查找Namenode,你不再需要localhost:8021,Namenode的端口号是50070。 24.
如何从SU转到Cloudera? 从SU转到Cloudera只需要键入exit。 25.
启动和关闭命令会用到哪些文件? Slaves及Masters。 26.
Slaves由什么组成? Slaves由主机的列表组成,每台1行,用于说明数据节点。 27.
Masters由什么组成? Masters同样是主机的列表组成,每台一行,用于说明第二Namenode服务器。 28.
hadoop-env.sh是用于做什么的? hadoop-env.sh提供了Hadoop中. JAVA_HOME的运行环境。 29.
Master文件是否提供了多个入口? 是的你可以拥有多个Master文件接口。 30.
Hadoop-env.sh文件当下的位置? hadoop-env.sh现在位于conf。 31.
在Hadoop_PID_DIR中,PID代表了什么? PID代表了“Process ID”。32.
/var/hadoop/pids用于做什么? /var/hadoop/pids用来存储PID。 33.
hadoop-metrics.properties文件的作用是? hadoop-metrics.properties被用做“Reporting”,控制Hadoop,初始状态是“not to report”。 34.
Hadoop需求什么样的网络? Hadoop核心使用Shell(SSH)来驱动从节点上的服务器进程,并在主节点和从节点之间使用password-less SSH连接。 35.
全分布式环境下为什么需求password-less SSH? 这主要因为集群中通信过于频繁,Job Tracker需要尽可能快的给Task Tracker发布任务。 36.
这会导致安全问题吗? 完全不用担心。Hadoop集群是完全隔离的,通常情况下无法从互联网进行操作。与众不同的配置,因此我们完全不需要在意这种级别的安全漏洞,比如说通过互联网侵入等等。Hadoop为机器之间的连接提供了一个相对安全的方式。 37.
SSH工作的端口号是? SSH工作的端口号是NO.22,当然可以通过它来配置,22是默认的端口号。 38.
SSH中的注意点还包括? SSH只是个安全的shell通信,可以把它当做NO.22上的一种协议,只需要配置一个密码就可以安全的访问。 39.
为什么SSH本地主机需要密码? 在SSH中使用密码主要是增加安全性,在某些情况下也根本不会设置密码通信。 40.
如果在SSH中添加key,是否还需要设置密码?篇二:Hadoop常见的45个面试题
? hadoop工作linux 1.Hadoop集群可以运行的3个模式 ? ? ? 单机(本地)模式 伪分布式模式 全分布式模式 2.
单机(本地)模式中的注意点? 在单机模式(standalone)中不会存在守护进程,所有东西都运行在一个JVM上。这里同样没有DFS,使用的是本地文件系统。单机模式适用于开发过程中运行MapReduce程序,这也是最少使用的一个模式。 3.
伪分布模式中的注意点? 伪分布式(Pseudo)适用于开发和测试环境,在这个模式中,所有守护进程都在同一台机器上运行。 4.
VM是否可以称为Pseudo? 不是,两个事物,同时Pseudo只针对Hadoop。 5.
全分布模式又有什么注意点? 全分布模式通常被用于生产环境,这里我们使用N台主机组成一个Hadoop集群,Hadoop守护进程运行在每台主机之上。这里会存在Namenode运行的主机,Datanode运行的主机,以及task tracker运行的主机。在分布式环境下,主节点和从节点会分开。 6.
Hadoop是否遵循UNIX模式? 是的,在UNIX用例下,Hadoop还拥有“conf”目录。 7.
Hadoop安装在什么目录下? Cloudera和Apache使用相同的目录结构,Hadoop被安装在cd/usr/lib/hadoop-0.20/。 8.
Namenode、Job tracker和task tracker的端口号是?Namenode,70;Job tracker,30;Task tracker,60。 9.
Hadoop的核心配置是什么? Hadoop的核心配置通过两个xml文件来完成:1,hadoop-default.xml;2,hadoop-site.xml。这些文件都使用xml格式,因此每个xml中都有一些属性,包括名称和值,但是当下这些文件都已不复存在。 10.
那当下又该如何配置? Hadoop现在拥有3个配置文件:1,core-site.xml;2,hdfs-site.xml;3,mapred-site.xml。这些文件都保存在conf/子目录下。 11.
RAM的溢出因子是? 溢出因子(Spill factor)是临时文件中储存文件的大小,也就是Hadoop-temp目录。 12.
fs.mapr.working.dir只是单一的目录? fs.mapr.working.dir只是一个目录。 13.
hdfs-site.xml的3个主要属性? ? ? ? dfs.name.dir决定的是元数据存储的路径以及DFS的存储方式(磁盘或是远端) dfs.data.dir决定的是数据存储的路径 fs.checkpoint.dir用于第二Namenode 14.
如何退出输入模式? 退出输入的方式有:1,按ESC;2,键入:q(如果你没有输入任何当下)或者键入:wq(如果你已经输入当下),并且按下Enter。 15.
当你输入hadoopfsck /造成“connection refused java exception’”时,系统究竟发生了什么? 这意味着Namenode没有运行在你的VM之上。 16.
我们使用Ubuntu及Cloudera,那么我们该去哪里下载Hadoop,或者是默认就与 Ubuntu一起安装?这个属于Hadoop的默认配置,你必须从Cloudera或者Edureka的dropbox下载,然后在你的系统上运行。当然,你也可以自己配置,但是你需要一个Linux box,Ubuntu或者是Red Hat。在Cloudera网站或者是Edureka的Dropbox中有安装步骤。 17.
“jps”命令的用处? 这个命令可以检查Namenode、Datanode、Task Tracker、 Job Tracker是否正常工作。 18.
如何重启Namenode? ? ? 点击stop-all.sh,再点击start-all.sh。 键入sudohdfs(Enter),su-hdfs(Enter),/etc/init.d/ha(Enter),及 /etc/init.d/hadoop-0.20-namenode start(Enter)。 19.
Fsck的全名? 全名是:File System Check。 20.
如何检查Namenode是否正常运行? 如果要检查Namenode是否正常工作,使用命令/etc/init.d/hadoop-0.20-namenode status或者就是简单的jps。
mapred.job.tracker命令的作用? 可以让你知道哪个节点是Job Tracker。 22.
/etc /init.d命令的作用是? /etc /init.d说明了守护进程(服务)的位置或状态,其实是LINUX特性,和Hadoop关系不大。23.
如何在浏览器中查找Namenode? 如果你确实需要在浏览器中查找Namenode,你不再需要localhost:8021,Namenode的端口号是50070。 24.
如何从SU转到Cloudera? 从SU转到Cloudera只需要键入exit。 25.
启动和关闭命令会用到哪些文件? Slaves及Masters。 26.
Slaves由什么组成? Slaves由主机的列表组成,每台1行,用于说明数据节点。 27.
Masters由什么组成? Masters同样是主机的列表组成,每台一行,用于说明第二Namenode服务器。 28.
hadoop-env.sh是用于做什么的? hadoop-env.sh提供了Hadoop中. JAVA_HOME的运行环境。 29.
Master文件是否提供了多个入口?是的你可以拥有多个Master文件接口。 30.
hadoop-env.sh文件当下的位置? hadoop-env.sh现在位于conf。 31.
在Hadoop_PID_DIR中,PID代表了什么? PID代表了“Process ID”。 32.
/var/hadoop/pids用于做什么? /var/hadoop/pids用来存储PID。 33.
hadoop-metrics.properties文件的作用是? hadoop-metrics.properties被用做“Reporting”,控制Hadoop报告,初始状态是“not to report”。 34.
Hadoop需求什么样的网络? Hadoop核心使用Shell(SSH)来驱动从节点上的服务器进程,并在主节点和从节点之间使用password-less SSH连接。 35.
全分布式环境下为什么需求password-less SSH? 这主要因为集群中通信过于频繁,Job Tracker需要尽可能快的给Task Tracker发布任篇三:Hadoop面试题整理 1
请列出你所知道的 hadoop 调度器 并简要说明其工作方法 随着MapReduce的流行,其开源实现Hadoop也变得越来越受推崇。在Hadoop系统中,有一个组件非常重要,那就是调度器,它的作用是将系统中空闲的资源按一定策略分配给作业。在Hadoop中,调度器是一个可插拔的模块,用户可以根据自己的实际应用要求设计调度器。Hadoop中常见的调度器有三种,分别为: (注:本文介绍的Hadoop调度器不够系统化,如果想了解更系统化的Hadoop调度器,可阅读我的最新书籍《Hadoop技术内幕:深入解析MapReduce架构设计与实现原理》(购买说明)第10章 “Hadoop多用户作业调度器分析”,分析了当前比较流行的FIFO、Capacity个Fair三种调度器的配置方法、实现机制和优缺点对比,当然,也介绍了其他类型的几种调度器。) (1)默认的调度器FIFO Hadoop中默认的调度器,它先按照作业的优先级高低,再按照到达时间的先后选择被执行的作业。 (2) 计算能力调度器Capacity Scheduler 支持多个队列,每个队列可配置一定的资源量,每个队列采用FIFO调度策略,为了防止同一个用户的作业独占队列中的资源,该调度器会对同一用户提交的作业所占资源量进行限定。调度时,首先按以下策略选择一个合适队列:计算每个队列中正在运行的任务数与其应该分得的计算资源之间的比值,选择一个该比值最小的队列;然后按以下策略选择该队列中一个作业:按照作业优先级和提交时间顺序选择,同时考虑用户资源量限制和内存限制。 (3)公平调度器Fair Scheduler 同计算能力调度器类似,支持多队列多用户,每个队列中的资源量可以配置,同一队列中的作业公平共享队列中所有资源,具体算法参见我的博文《Hadoop公平调度器算法解析》 实际上,Hadoop的调度器远不止以上三种,最近,出现了很多针对新型应用的Hadoop调度器。 2 HDFS的存储机制 1. HDFS开创性地设计出一套文件存储方式,即对文件分割后分别存放; 2. HDFS将要存储的大文件进行分割,分割后存放在既定的存储块(Block)中,并通过预先设定的优化处理,模式对存储的数据进行预处理,从而解决了大文件储存与计算的需求; 3. 一个HDFS集群包括两大部分,即NameNode与DataNode。一般来说,一个集群中会有一个NameNode和多个DataNode共同工作; 4. NameNode是集群的主服务器,主要是用于对HDFS中所有的文件及内容数据进行维护,并不断读取记录集群中DataNode主机情况与工作状态,并通过读取与写入镜像日志文件的方式进行存储; 5. DataNode在HDFS集群中担任任务具体执行角色,是集群的工作节点。文件被分成若干个相同大小的数据块,分别存储在若干个DataNode上,DataNode会定期向集群内NameNode发送自己的运行状态与存储内容,并根据NameNode发送的指令进行工作; 6. NameNode负责接受客户端发送过来的信息,然后将文件存储位置信息发送给提交请求的客户端,由客户端直接与DataNode进行联系,从而进行部分文件的运算与操作。 7. Block是HDFS的基本存储单元,默认大小是64M; 8. HDFS还可以对已经存储的Block进行多副本备份,将每个Block至少复制到3个相互独立的硬件上,这样可以快速恢复损坏的数据; 9. 用户可以使用既定的API接口对HDFS中的文件进行操作; 10. 当客户端的读取操作发生错误的时候,客户端会向NameNode报告错误,并请求NameNode排除错误的DataNode后后重新根据距离排序,从而获得一个新的DataNode的读取路径。如果所有的DataNode都报告读取失败,那么整个任务就读取失败; 11. 对于写出操作过程中出现的问题,FSDataOutputStream并不会立即关闭。客户端向NameNode报告错误信息,并直接向提供备份的DataNode中写入数据。备份DataNode被升级为首选DataNode,并在其余2个DataNode中备份复制数据。NameNode对错误的DataNode进行标记以便后续对其进行处理 3 MapReduce 中的两表 join 几种方案 1. 概述 在传统数据库(如:MYSQL)中,JOIN操作是非常常见且非常耗时的。而在HADOOP中进行JOIN操作,同样常见且耗时,由于Hadoop的独特设计思想,当进行JOIN操作时,有一些特殊的技巧。 本文首先介绍了Hadoop上通常的JOIN实现方法,然后给出了几种针对不同输入数据集的优化方法。 2. 常见的join方法介绍 假设要进行join的数据分别来自File1和File2. 2.1 reduce side join reduce side join是一种最简单的join方式,其主要思想如下: 在map阶段,map函数同时读取两个文件File1和File2,为了区分两种来源的key/value数据对,对每条数据打一个标签(tag),比如:tag=0表示来自文件File1,tag=2表示来自文件File2。即:map阶段的主要任务是对不同文件中的数据打标签。 在reduce阶段,reduce函数获取key相同的来自File1和File2文件的value list, 然后对于同一个key,对File1和File2中的数据进行join(笛卡尔乘积)。即:reduce阶段进行实际的连接操作。 REF:hadoop join之reduce side join http://blog.csdn.net/huashetianzu/article/details/7819244 2.2 map side join 之所以存在reduce side join,是因为在map阶段不能获取所有需要的join字段,即:同一个key对应的字段可能位于不同map中。Reduce side join是非常低效的,因为shuffle阶段要进行大量的数据传输。 Map side join是针对以下场景进行的优化:两个待连接表中,有一个表非常大,而另一个表非常小,以至于小表可以直接存放到内存中。这样,我们可以将小表复制多份,让每个map task内存中存在一份(比如存放到hash table中),然后只扫描大表:对于大表中的每一条记录key/value,在hash table中查找是否有相同的key的记录,如果有,则连接后输出即可。 为了支持文件的复制,Hadoop提供了一个类DistributedCache,使用该类的方法如下: (1)用户使用静态方法DistributedCache.addCacheFile()指定要复制的文件,它的参数是文件的URI(如果是HDFS上的文件,可以这样:hdfs://namenode:9000/home/XXX/file,其中9000是自己配置的NameNode端口号)。JobTracker在作业启动之前会获取这个URI列表,并将相应的文件拷贝到各个TaskTracker的本地磁盘上。(2)用户使用DistributedCache.getLocalCacheFiles()方法获取文件目录,并使用标准的文件读写API读取相应的文件。 REF:hadoop join之map side join http://blog.csdn.net/huashetianzu/article/details/7821674 2.3 Semi Join Semi Join,也叫半连接,是从分布式数据库中借鉴过来的方法。它的产生动机是:对于reduce side join,跨机器的数据传输量非常大,这成了join操作的一个瓶颈,如果能够在map端过滤掉不会参加join操作的数据,则可以大大节省网络IO。 实现方法很简单:选取一个小表,假设是File1,将其参与join的key抽取出来,保存到文件File3中,File3文件一般很小,可以放到内存中。在map阶段,使用DistributedCache将File3复制到各个TaskTracker上,然后将File2中不在File3中的key对应的记录过滤掉,剩下的reduce阶段的工作与reduce side join相同。 更多关于半连接的介绍,可参考:半连接介绍:/view/ae.html REF:hadoop join之semi join http://blog.csdn.net/huashetianzu/article/details/7823326 2.4 reduce side join + BloomFilter 在某些情况下,SemiJoin抽取出来的小表的key集合在内存中仍然存放不下,这时候可以使用BloomFiler以节省空间。 BloomFilter最常见的作用是:判断某个元素是否在一个集合里面。它最重要的两个方法是:add() 和contains()。最大的特点是不会存在 false negative,即:如果contains()返回false,则该元素一定不在集合中,但会存在一定的 false positive,即:如果contains()返回true,则该元素一定可能在集合中。 因而可将小表中的key保存到BloomFilter中,在map阶段过滤大表,可能有一些不在小表中的记录没有过滤掉(但是在小表中的记录一定不会过滤掉),这没关系,只不过增加了少量的网络IO而已。 更多关于BloomFilter的介绍,可参考:http://blog.csdn.net/jiaomeng/article/details/1495500 3. 二次排序 在Hadoop中,默认情况下是按照key进行排序,如果要按照value进行排序怎么办?即:对于同一个key,reduce函数接收到的value list是按照value排序的。这种应用需求在join操作中很常见,比如,希望相同的key中,小表对应的value排在前面。 有两种方法进行二次排序,分别为:buffer and in memory sort和 value-to-key conversion。 对于buffer and in memory sort,主要思想是:在reduce()函数中,将某个key对应的所有value保存下来,然后进行排序。 这种方法最大的缺点是:可能会造成out of memory。 对于value-to-key conversion,主要思想是:将key和部分value拼接成一个组合key(实现WritableComparable接口或者调用setSortComparatorClass函数),这样reduce获取的结果便是先按key排序,后按value排序的结果,需要注意的是,用户需要自己实现Paritioner,以便只按照key进行数据划分。Hadoop显式的支持二次排序,在Configuration类中有个setGroupingComparatorClass()方法,可用于设置排序group的key值,具体参考:/xuxm2007/archive//2165805.html 4. 后记 最近一直在找工作,由于简历上写了熟悉Hadoop,所以几乎每个面试官都会问一些Hadoop相关的东西,而 Hadoop上Join的实现就成了一道必问的问题,而极个别公司还会涉及到DistributedCache原理以及怎样利用DistributedCache进行Join操作。为了更好地应对这些面试官,特整理此文章。 4 介绍一下hbase 过滤器 一、过滤器(Filter) 基础API中的查询操作在面对大量数据的时候是非常苍白的,这里Hbase提供了高级的查询方法:Filter。Filter可以根据簇、列、版本等更多的条件来对数据进行过滤,基于Hbase本身提供的三维有序(主键有序、列有序、版本有序),这些Filter可以高效的完成查询过滤的任务。带有Filter条件的RPC查询请求会把Filter分发到各个RegionServer,是一个服务器端(Server-side)的过滤器,这样也可以降低网络传输的压力。 要完成一个过滤的操作,至少需要两个参数。一个是抽象的操作符,Hbase提供了枚举类型的变量来表示这些抽象的操作符:LESS/LESS_OR_EQUAL/EQUAL/NOT_EUQAL等;另外一个就是具体的比较器(Comparator),代表具体的比较逻辑,如果可以提高字节级的比较、字符串级的比较等。有了这两个参数,我们就可以清晰的定义筛选的条件,过滤数据。
收藏代码 CompareFilter(CompareOp compareOp, WritableByteArrayComparable valueComparator) CompareFilter是高层的抽象类,下面我们将看到它的实现类和实现类代表的各种过滤条件。这里实现类实际上代表的是参数中的过滤器过滤的内容,可以使主键、簇名、列值等,这就是由CompareFilter决定了。 行过滤器(RowFilter) 行过滤器的比较对象是行主键
收藏代码 Scan scan = new Scan(); Filter filter1 = new pareOp.LESS_OR_EUQAL, new BinaryComparator(Bytes.toBytes(&hello&))); scan.setFilter(filter1); scan.close();
例中的Filter会将所有的小于等于“Hello”的主键过滤出来。 簇过滤器(FamilyFilter) 簇过滤器过滤的是簇的名字。 列过滤器(QualifierFilter) 列过滤器过滤的是列的名字。 值过滤器(ValueFilter) 值过滤器过滤的是扫描对象的值。 单值过滤器(SingleColumnValueFilter) 单值过滤器是以特定列的值为过滤内容,与值过滤器不同的是,这里是特定的列,而值过滤器比较的是行内的所有列。所有在使用单值过滤器的时候要指定比较的列的坐标。
收藏代码 SingleColumnValueFilter(byte[] family, byte[] qualifier, CompareOp compareOp, WritableByteArrayComparable comparator)
对于找不到该列的行,可以有特殊的处理 Java代码
收藏代码 void setFilterIfMissing(boolean filterIfMissing)
默认缺省行将被包含进过滤的结果集中。 前缀过滤器(PrefixFilter) 前缀过滤器将会过滤掉不匹配的记录,过滤的对象是主键的值。 Java代码
收藏代码 PrefixFilter(byte[] prefix)
页过滤器(PageFilter) 页过滤器可以根据主键有序返回固定数量的记录,这需要客户端在遍历的时候记住页开始的地方,配合scan的startkey一起使用。
收藏代码 PageFilter(int size)
键过滤器(KeyOnlyFilter) 键过滤器可以简单的设置过滤的结果集中只包含键而忽略值,这里有一个选项可以把结果集的值保存为值的长度。 FirstKeyOnlyFilter 在键过滤器的基础上,根据列有序,只包含第一个满足的键。 ColumnPrefixFilter 这里过滤的对象是列的值。 TimestampsFilter
收藏代码 TimestampsFilter(List&Long& times)
这里参数是一个集合,只有包含在集合中的版本才会包含在结果集中。 包装类过滤器,此类过滤器要通过包装其他的过滤器才有意义,是其他过滤器的一种加强。 SkipFilter
收藏代码 SkipFilter(Filter filter)
过滤器集合(FilterList) Hbase的过滤器设计遵照于设计模式中的组合模式,以上的所有过滤器都可以叠加起来共同作用于一次查询。 二、计数器(Counter) Hbase提供一个计数器工具可以方便快速的进行计数的操作,而免去了加锁等保证原子性的操作。但是实质上,计数器还是列,有自己的簇和列名。值得注意的是,维护计数器的值最好是用Hbase提供的API,直接操作更新很容易引起数据的混乱。 计数器的增量可以是正数负数,正数代表加,负数代表减。
收藏代码 long icrementColumnValue(byte[] row, byte[] famuly, byte[] qualifier, long amount) Result increment(Increment increment)
三、协处理器(Coprocessor) 协处理器的思想是把处理的复杂代码分发到各个RegionServer,使大部分的计算可以在服务器端,或者扫描的时候完成,提高处理的效率。形式上比较类似RDBMS中的存储过程,不同的是,存储过程的原理是在服务器端进行预处理等优化,而协处理器仅仅只是服务器处理,这里又有点类似于Map-Reduce中的Map阶段。 协处理器(Coprocesssor)有两种,一种是观察者(Obsever)另外一种是Endpoint(LZ跪了,实在不知道翻译成啥)。 每个协处理器都有一个优先级,优先级分为USER/SYSTEM,优先级决定处理器的执行顺序,SYSTEM级别的处理器永远先于USER。 每个处理器都有自己的执行环境(CoprocessorEnvironment),这个环境包含当前集群和请求的状态等信息,是处理中重要的一部分,以构造函数参数的形式被传入到处理器。 另外就是CoprocessorHost,这是Hbase管理协处理器的类,用来维护所有的处理器和其环境。
协处理器的加载有两种方式,一种是通过配置文件,在配置文件中指定加载路径、类名等,通过这种方式加载的处理器都是SYSTEM级别的,会作用于所有的请求,所有的表;另一种方式是通过在创建表的时候在表中指定,这种方式既可以创建全局的SYSTEM级别的处理器,也可以创建USER级别的处理器,USER级别的处理器是针对表的。
收藏代码 Path path = new Paht(&test.jar&); HTableDescriptor htd = new HTableDescriptor(&test&); htd.addFamily(new HColumnDescriptor(&family1&)); htd.setValue(&Coprocessor$1&, path.toString + &|& + className + &|& + Coprocessor.Priority.USER); HBaseAdmin admin = new HBaseAdmin(conf); admin.createTable(htd);
这里setValue方法有两个参数,第一个参数是协处理器的名字,$后面跟的是影响执行顺序的序号;第二个参数是&path&|&classname&|&priority&。 Observer 这是第一种处理器,观察者,观察者有三种,分别用来监听RegionServerObserver、MasterServerObserver、WALObserver。 RegionServer监听的是Region Server上的操作,如在Region Server上的Get、Put等。操作被赋予生命周期:Pending open--open--Pending close 监听器是可以监听生命周期中的各个阶段,并对其做出处理。 每一个监听的方法都有一个上下文参数(Context),通过Context参数可以直接的操作请求的声明周期。 Java代码
收藏代码 void bypass(); void complete(); MasterObserver监听的是Master Server上的操作,有点类似RDBMS中的DDL的操作如表操作、列操作等。 具体的操作和RegionServer比较类似。Endpoint 这是第二种处理器,Endpoint相当于被分发到各个RegionServer上的存储过程,可以在客户端远程调用的方法。Endpoint的存在使我们可以进行一些服务器端的计算,如服务器聚集、求和等运算,弥补了查询API的不足。服务器端计算的优势是显而易见的,它可以降低网络传输的数据量,合理利用服务器资源。 从功能上可以看出Endpoint是一个基于RPC调用的模块,所以在实现自己的Endpoint时候需要定义我们自己的通信协议。在Hbase中,通信协议被抽象为CoprocessorProtocol接口,要实现我们的协议,我们要创建协议接口继承自CoprocessorProtocol接口,然后再实现我们的协议类。 Java代码
收藏代码 public interface MyProtocol extends CoprocessorProtocol { public int work(); } 协议类本身也是处理器,所以还要继承BaseEndpointCoprocessor类。
收藏代码 public class MyEndpoint extends BaseEndpointCoprocessor implements MyProtocol { public int work() { Sytem.out.println(&hello&); } } 在抽象的父类BaseEndpointCoprocessor中还提供了一些有用的方法,如我们可以拿到对应的环境类。 Java代码
收藏代码 RegionCoprocessorEnvironment getEnvironment()
配置好Endpoint重启集群环境以后,我们的实现类会被分发到各个RegionServer,通过HTable实例的方法我们可以调用到Endpoint。
收藏代码 &T extends CoprocessorProtocol, R& Map&byte[], R& coprocessorExec(Class&T& protocol, byte[] startKey, byte[] endKey, Batch.Call&T, R& callable);
startKey和endKey用于确定哪些RegionServer将执行Endpoint, Batch中的内部类将决定协议中方法的调用。 四、 HTablePool 连接池 在Hbase中,创建一个代表表的HTable实例是一个耗时且很占资源的操作,类似操作数据库,我们也需要建立我们自己的连接池,于是有了代表连接池的抽象类:HTable。
收藏代码 HTablePool(Configuaration conf, int maxSize) HTablePool(Configuaration conf, int maxSize, HTableInterfaceFactory factory)
创建HTable需要配置文件的实例,连接池的最大连接数也在构造方法中设置。另外,如果想要自己控制HTable被创建的过程,则需要实现自己的工厂方法。在连接池中,最大连接数(maxSize)的含义是,连接池管理的最大的连接数,当所需要的连接数超过最大值时,会临时的创建连接来满足需求,但是这些连接在使用完毕之后会被直接释放且丢弃而不会进入连接池被管理,所以最大连接数代表的是连接池中最大被管理的连接数,而不是使用连接池最大可使用的连接数。
收藏代码 HTableInterface getTable(String tableName) HTableInterface getTable(byte[] tableName) void putTable(HTableInterface table)
需要注意的是,使用完连接以后需要手动的调用putTable方法将连接放回池中。
5 hbase 性能调优 我们经常看到一些文章吹嘘某产品如何如何快,如何如何强,而自己测试时却不如描述的一些数据。其实原因可能在于你还不是真正理解其内部结构,对于其性能调优方法不够了解。本文转自TaoBao的Ken Wu同学的博客,是目前看到比较完整的HBase调优文章。 原文链接:HBase性能调优 因官方Book Performance Tuning部分章节没有按配置项进行索引,不能达到快速查阅的效果。所以我以配置项驱动,重新整理了原文,并补充一些自己的理解,如有错误,欢迎指正。 配置优化 zookeeper.session.timeout 默认值:3分钟(180000ms) 说明:RegionServer与Zookeeper间的连接超时时间。当超时时间到后,ReigonServer会被Zookeeper从RS集群清单中移除,HMaster收到移除通知后,会对这台server负责的regions重新balance,让其他存活的RegionServer接管. 调优:这个timeout决定了RegionServer是否能够及时的failover。设置成1分钟或更低,可以减少因等待超时而被延长的failover时间。 不过需要注意的是,对于一些Online应用,RegionServer从宕机到恢复时间本身就很短的(网络闪断,crash等故障,运维可快速介入),如果调低timeout时间,反而会得不偿失。因为当ReigonServer被正式从RS集群中移除时,HMaster就开始做balance了(让其他RS根据故障机器记录的WAL日志进行恢复)。当故障的RS在人工介入恢复后,这个balance动作是毫无意义的,反而会使负载不均匀,给RS带来更多负担。特别是那些固定分配regions的场景。 hbase.regionserver.handler.count 默认值:10 说明:RegionServer的请求处理IO线程数。 调优:这个参数的调优与内存息息相关。 较少的IO线程,适用于处理单次请求内存消耗较高的Big PUT场景(大容量单次PUT或设置了较大cache的scan,均属于Big PUT)或ReigonServer的内存比较紧张的场景。 较多的IO线程,适用于单次请求内存消耗低,TPS要求非常高的场景。设置该值的时候,以监控内存为主要参考。 这里需要注意的是如果server的region数量很少,大量的请求都落在一个region上,因快速充满memstore触发flush导致的读写锁会影响全局TPS,不是IO线程数越高越好。 压测时,开启Enabling RPC-level logging,可以同时监控每次请求的内存消耗和GC的状况,最后通过多次压测结果来合理调节IO线程数。 这里是一个案例Hadoop and HBase Optimization for Read Intensive Search Applications,作者在SSD的机器上设置IO线程数为100,仅供参考。 hbase.hregion.max.filesize 默认值:256M 说明:在当前ReigonServer上单个Reigon的最大存储空间,单个Region超过该值时,这个Region会被自动split成更小的region。 调优:小region对split和compaction友好,因为拆分region或compact小region里的storefile速度很快,内存占用低。缺点是split和compaction会很频繁。 特别是数量较多的小region不停地split, compaction,会导致集群响应时间波动很大,region数量太多不仅给管理上带来麻烦,甚至会引发一些Hbase的bug。 一般512以下的都算小region。 大region,则不太适合经常split和compaction,因为做一次compact和split会产生较长时间的停顿,对应用的读写性能冲击非常大。此外,大region意味着较大的storefile,compaction时对内存也是一个挑战。 当然,大region也有其用武之地。如果你的应用场景中,某个时间点的访问量较低,那么在此时做compact和split,既能顺利完成split和compaction,又能保证绝大多数时间平稳的读写性能。 既然split和compaction如此影响性能,有没有办法去掉? compaction是无法避免的,split倒是可以从自动调整为手动。 只要通过将这个参数值调大到某个很难达到的值,比如100G,就可以间接禁用自动split(RegionServer不会对未到达100G的region做split)。 再配合RegionSplitter这个工具,在需要split时,手动split。 手动split在灵活性和稳定性上比起自动split要高很多,相反,管理成本增加不多,比较推荐online实时系统使用。 内存方面,小region在设置memstore的大小值上比较灵活,大region则过大过小都不行,过大会导致flush时app的IO wait增高,过小则因store file过多影响读性能。 hbase.regionserver.global.memstore.upperLimit/lowerLimit 默认值:0.4/0.35 upperlimit说明:hbase.hregion.memstore.flush.size 这个参数的作用是 当单个memstore达到指定值时,flush该memstore。但是,一台ReigonServer可能有成百上千个memstore,每个memstore也许未达到flush.size,jvm的heap就不够用了。该参数就是为了限制memstores占用的总内存。 当ReigonServer内所有的memstore所占用的内存总和达到heap的40%时,HBase会强制block所有的更新并flush这些memstore以释放所有memstore占用的内存。 lowerLimit说明: 同upperLimit,只不过当全局memstore的内存达到35%时,它不会flush所有的memstore,它会找一些内存占用较大的memstore,做个别flush,当然更新还是会被block。lowerLimit算是一个在全局flush导致性能暴跌前的补救措施。为什么说是性能暴跌?可以想象一下,如果memstore需要在一段较长的时间内做全量flush,且这段时间内无法接受任何读写请求,对HBase集群的性能影响是很大的。 调优:这是一个Heap内存保护参数,默认值已经能适用大多数场景。它的调整一般是为了配合某些专属优化,比如读密集型应用,将读缓存开大,降低该值,腾出更多内存给其他模块使用。 这个参数会给使用者带来什么影响? 比如,10G内存,100个region,每个memstore 64M,假设每个region只有一个memstore,那么当100个memstore平均占用到50%左右时,就会达到lowerLimit的限制。假设此时,其他memstore同样有很多的写请求进来。在那些大的region未flush完,就可能又超过了upperlimit,则所有region都会被block,开始触发全局flush。 不过,除了你的内存非常小或你的应用场景里大多数都是读,我觉得不需要去调这个参数。 hfile.block.cache.size 默认值:0.2 说明:storefile的读缓存占用Heap的大小百分比,0.2表示20%。该值直接影响数据读的性能。 调优:当然是越大越好,如果读比写少,开到0.4-0.5也没问题。如果读写较均衡,0.3左右。如果写比读多,果断默认吧。设置这个值的时候,你同时要参考 hbase.regionserver.global.memstore.upperLimit ,该值是memstore占heap的最大百分比,两个参数一个影响读,一个影响写。如果两值加起来超过80-90%,会有OOM的风险,谨慎设置。 hbase.hstore.blockingStoreFiles 默认值:7 说明:在compaction时,如果一个Store(Coulmn Family)内有超过7个storefile需要合并,则block所有的写请求,进行flush,限制storefile数量增长过快。调优:block写请求会影响当前region的性能,将值设为单个region可以支撑的最大store file数量会是个不错的选择,即允许comapction时,memstore继续生成storefile。最大storefile数量可通过region size/memstore size来计算。如果你将region size设为无限大,那么你需要预估一个region可能产生的最大storefile数。 hbase.hregion.memstore.block.multiplier 默认值:2 说明:当一个region里的memstore超过单个memstore.size两倍的大小时,block该region的所有请求,进行flush,释放内存。虽然我们设置了memstore的总大小,比如64M,但想象一下,在最后63.9M的时候,我Put了一个100M的数据,此时memstore的大小会瞬间暴涨到超过预期的memstore.size。这个参数的作用是当memstore的大小增至超过memstore.size时,block所有请求,遏制风险进一步扩大。 调优: 这个参数的默认值还是比较靠谱的。如果你预估你的正常应用场景(不包括异常)不会出现突发写或写的量可控,那么保持默认值即可。如果正常情况下,你的写请求量就会经常暴长到正常的几倍,那么你应该调大这个倍数并调整其他参数值,比如hfile.block.cache.size和hbase.regionserver.global.memstore.upperLimit/lowerLimit,以预留更多内存,防止HBase server OOM。 其他 启用LZO压缩 LZO对比Hbase默认的GZip,前者性能较高,后者压缩比较高,具体参见Using LZO Compression。对于想提高HBase读写性能的开发者,采用LZO是比较好的选择。对于非常在乎存储空间的开发者,则建议保持默认。 不要在一张表里定义太多的Column Family Hbase目前不能良好的处理超过包含2-3个CF的表。因为某个CF在flush发生时,它邻近的CF也会因关联效应被触发flush,最终导致系统产生更多IO。 批量导入 在批量导入数据到Hbase前,你可以通过预先创建regions,来平衡数据的负载。详见Table Creation: Pre-Creating Regions 避免CMS concurrent mode failure HBase使用CMS GC。默认触发GC的时机是当年老代内存达到90%的时候,这个百分比由 -XX:CMSInitiatingOccupancyFraction=N 这个参数来设置。concurrent mode failed发生在这样一个场景: 当年老代内存达到90%的时候,CMS开始进行并发垃圾收集,于此同时,新生代还在迅速不断地晋升对象到年老代。当年老代CMS还未完成并发标记时,年老代满了,悲剧就发生了。CMS因为没内存可用不得不暂停mark,并触发一次全jvm的stop the world(挂起所有线程),然后采用单线程拷贝方式清理所有垃圾对象。这个过程会非常漫长。为了避免出现concurrent mode failed,我们应该让GC在未到90%时,就触发。 通过设置-XX:CMSInitiatingOccupancyFraction=N 这个百分比, 可以简单的这么计算。如果你的hfile.block.cache.size 和hbase.regionserver.global.memstore.upperLimit 加起来有60%(默认),那么你可以设置 70-80,一般高10%左右差不多。 Hbase客户端优化 AutoFlush 将HTable的setAutoFlush设为false,可以支持客户端批量更新。即当Put填满客户端flush缓存时,才发送到服务端。默认是true。 Scan Caching scanner一次缓存多少数据来scan(从服务端一次抓多少数据回来scan)。 默认值是 1,一次只取一条。 Scan Attribute Selection scan时建议指定需要的Column Family,减少通信量,否则scan操作默认会返回整个row的所有数据(所有Coulmn Family)。 Close ResultScanners 通过scan取完数据后,记得要关闭ResultScanner,否则RegionServer可能会出现问题(对应的Server资源无法释放)。 Optimal Loading of Row Keys 当你scan一张表的时候,返回结果只需要row key(不需要CF, qualifier,values,timestaps)时,你可以在scan实例中添加一个filterList,并设置 MUST_PASS_ALL操作,filterList中addFirstKeyOnlyFilter或KeyOnlyFilter。这样可以减少网络通信量。 Turn off WAL on Puts 当Put某些非重要数据时,你可以设置writeToWAL(false),来进一步提高写性能。writeToWAL(false)会在Put时放弃写WAL log。风险是,当RegionServer宕机时,可能你刚才Put的那些数据会丢失,且无法恢复。 启用Bloom Filter Bloom Filter通过空间换时间,提高读操作性能。 6 hbase 预分区设计 HBase中,表会被划分为1...n个Region,被托管在RegionServer中。Region二个重要的属性:StartKey与 EndKey表示这个Region维护的rowKey范围,当我们要读/写数据时,如果rowKey落在某个start-end key范围内,那么就会定位到目标region并且读/写到相关的数据。简单地说,有那么一点点类似人群划分,1-15岁为小朋友,16-39岁为年轻 人,40-64为中年人,65岁以上为老年人。(这些数值都是拍脑袋出来的,只是举例,非真实),然后某人找队伍,然后根据年龄,处于哪个范围,就找到它 所属的队伍。 : ( 有点废话了。。。。 然后,默认地,当我们只是通过HBaseAdmin指定TableDescriptor来创建一张表时,只有一个region,正处于混沌时 期,start-end key无边界,可谓海纳百川。啥样的rowKey都可以接受,都往这个region里装,然而,当数据越来越多,region的size越来越大时,大到 一定的阀值,hbase认为再往这个region里塞数据已经不合适了,就会找到一个midKey将region一分为二,成为2个region,这个过 程称为分裂(region-split).而midKey则为这二个region的临界,左为N无下界,右为M无上界。& midKey则为阴被塞到N区,& midKey则会被塞到M区。 如何找到midKey?涉及的内容比较多,暂且不去讨论,最简单的可以认为是region的总行数 / 2 的那一行数据的rowKey.虽然实际上比它会稍复杂点。 如果我们就这样默认地,建表,表里不断地Put数据,更严重的是我们的rowkey还是顺序增大的,是比较可怕的。存在的缺点比较明显。 首先是热点写,我们总是会往最大的start-key所在的region写东西,因为我们的rowkey总是会比之前的大,并且hbase的是按升序方式排序的。所以写操作总是被定位到无上界的那个region中。 其次,由于写热点,我们总是往最大start-key的region写记录,之前分裂出来的region不会再被写数据,有点被打进冷宫的赶脚,它们都处于半满状态,这样的分布也是不利的。
如果在写比较频率的场景下,数据增长快,split的次数也会增多,由于split是比较耗时耗资源的,所以我们并不希望这种事情经常发生。 ............ 看到这些缺点,我们知道,在集群的环境中,为了得到更好的并行性,我们希望有好的load blance,让每个节点提供的请求处理都是均等的。我们也希望,region不要经常split,因为split会使server有一段时间的停顿,如何能做到呢? 随机散列与预分区。二者结合起来,是比较完美的,预分区一开始就预建好了一部分region,这些region都维护着自已的start-end keys,再配合上随机散列,写数据能均等地命中这些预建的region,就能解决上面的那些缺点,大大地提高了性能。 提供2种思路: hash 与 partition. 一、hash就是rowkey前面由一串随机字符串组成,随机字符串生成方式可以由SHA或者MD5等方式生成,只要region所管理的start-end keys范围比较随机,那么就可以解决写热点问题。 long currentId = 1L; byte [] rowkey = Bytes.add(MD5Hash.getMD5AsHex(Bytes.toBytes(currentId)).substring(0, 8).getBytes(), Bytes.toBytes(currentId));
假设rowKey原本是自增长的long型,可以将rowkey转为hash再转为bytes,加上本身id 转为bytes,组成rowkey,这样就生成随便的rowkey。那么对于这种方式的rowkey设计,如何去进行预分区呢? 1.取样,先随机生成一定数量的rowkey,将取样数据按升序排序放到一个集合里 2.根据预分区的region个数,对整个集合平均分割,即是相关的splitKeys. 3.HBaseAdmin.createTable(HTableDescriptor tableDescriptor,byte[][] splitkeys)可以指定预分区的splitKey,即是指定region间的rowkey临界值.
以上,就已经按hash方式,预建好了分区,以后在插入数据的时候,也要按照此rowkeyGenerator的方式生成rowkey,有兴趣的话,也可以做些试验,插入些数据,看看数据的分布。 二、partition故名思义,就是分区式,这种分区有点类似于mapreduce中的partitioner,将区域用长整数(Long)作为分区号,每 个region管理着相应的区域数据,在rowKey生成时,将id取模后,然后拼上id整体作为rowKey.这个比较简单,不需要取 样,splitKeys也非常简单,直接是分区号即可。直接上代码吧:
calcSplitKeys方法比较单纯,splitKey就是partition的编号,我们看看测试类: Java代码
通过partition实现的loadblance写的话,当然生成rowkey方式也要结合当前的region数目取模而求得,大家同样也可以做些实验,看看数据插入后的分布。 在这里也顺提一下,如果是顺序的增长型原id,可以将id保存到一个数据库,传统的也好,redis的也好,每次取的时候,将数值设大1000左右,以后 id可以在内存内增长,当内存数量已经超过1000的话,再去load下一个,有点类似于oracle中的sqeuence.
随机分布加预分区也不是一劳永逸的。因为数据是不断地增长的,随着时间不断地推移,已经分好的区域,或许已经装不住更多的数据,当然就要进一步进行 split了,同样也会出现性能损耗问题,所以我们还是要规划好数据增长速率,观察好数据定期维护,按需分析是否要进一步分行手工将分区再分好,也或者是 更严重的是新建表,做好更大的预分区然后进行数据迁移。
7 yarn 编程模型
文章思路: 首先提出第一代MRv1的局限性,然后解释YARN是怎么克服这些局限性的,接着说了YARN的编程模型,说了YARN的组成,YARN的通信协议和YARN的运行过程。通过这样的描述来认识YARN的。 MRv1的局限性 YARN是在MRv1的基础上演化而来,它克服了MRv1的各种局限性: 1:扩展性差 MRv1中,Jobracker同事兼备了资源管理和作业控制两个功能。 2:可靠性差MRv1才用了master/slave结构,master存在单点故障的问题。 3:资源利用率低 MRv1采用了基于槽位的资源分配模型,槽位是一种粗粒度的资源划分单位,通常一个 任务不会用完槽位对应的资源,且其他任务无法使用这些空闲的资源。 4:无法支持多种计算框架。 不能支持新的计算框架:包括内存计算框架,流式计算框架和迭代式计算框架。 第二代的mapreduce框架的TaskScheduler就是yarn YARN的编程模型 1:保证编程模型的向下兼容性,MRv2重用了MRv1的编程模型和数据处理引擎,但运行环境被重写。 2:编程模型与数据处理引擎 mapreduce应用程序编程接口有两套:新的API(mapred)和旧的API(mapreduce) 采用MRv1旧的API编写的程序可直接运行在MRv2上 采用MRv1新的API编写的程序需要使用MRv2编程库重新编译并修改不兼容的参数 和返回值 3:运行时环境 MRv1:Jobracker和Tasktracker MRv2:YARN和ApplicationMaster
YARN的组成 yarn主要由ResourceManager,NodeManager,ApplicationMaster和Container等几个组件组成。 ResourceManager(RM) RM是全局资源管理器,负责整个系统的资源管理和分配。 主要由两个组件组成:调度器和应用 程序管理器(ASM) 调度器 调度器根据容量,队列等限制条件,将系统中的资源分配给各个正在运行的应用程序 不负责具体应用程序的相关工作,比如监控或跟踪状态 不负责重新启动失败任务 资源分配单位用“资源容器”resource Container表示 Container是一个动态资源分配单位,它将内存,CPU,磁盘,网络等资源封装在一起,从而限定每个任务的资源量 调度器是一个可插拔的组件,用户可以自行设计 YARN提供了多种直接可用的调度器,比如fair Scheduler和Capacity Scheduler等。 应用程序管理器 负责管理整个系统中所有应用程序 ApplicationMaster(AM) 用户提交的每个应用程序均包含一个AM AM的主要功能 与RM调度器协商以获取资源(用Container表示) 将得到的任务进一步分配给内部的任务 与NM通信以自动/停止任务 监控所有任务运行状态,并在任务运行失败时重新为任务申请资源以重启任务 当前YARN自带了两个AM实现 一个用于演示AM编写方法的实例程序distributedshell 一个用于Mapreduce程序---MRAppMaster 其他的计算框架对应的AM正在开发中,比如spark等。 Nodemanager(NM)和Container NM是每个节点上的资源和任务管理器 定时向RM本节点上的资源使用情况和各个Container的运行状态 接收并处理来自AM的Container启动/停止等各种要求 Container是YARN中的资源抽象,它封装了某个节点上的多维度资源 YARN会为每个任务分配一个Container,且改任务只能使用该Container中描述的资源 Container不同于MRv1的slot,它是一个动态资源划分单位,是根据应用程序的需求动态产生的 yarn的通信协议 YARN主要由以下几个协议组成 ApplicationClientProtocol Jobclient通过该RPC协议提交应用才程序,查询应用程序状态等 ResourceManagerAdministrationProtocol Admin通过该协议更新系统配置文件,比如节点黑名单,用户队列权限等。 ApplicationMasterProtocol AM通过该RPC协议想RM注册和撤销自己,并为各个任务申请资源 ContainerManagementProtocol AM通过要求NM启动或者停止Container,获取各个Container的使用状态等信息 ResourceTracker NM通过该RPC协议向RM注册,并定时发送心跳信息当前节点的资源使用情况和Container运行状况 YARN的工作流程
文字描述一下这个过程: 1:由客户端提交一个应用,由RM的ASM接受应用请求 提交过来的应用程序包括哪些内容: a:ApplicationMaster b:启动Applicationmaster的命令 c:本身应用程序的内容 2:提交了三部分内容给RM,然后RM找NodeManager,然后 Nodemanager就启用Applicationmaster,并分配Container
接下来我们就要执行这个任务了, 3:但是执行任务需要资源,所以我们得向RM的ASM申请执行任务的资源(它会在RM这儿注册一下,说我已经启动了,注册了以后就可以通过RM的来管理,我们用户也可以通过RM的web客户端来监控任务的状态)ASM只是负责APplicationMaster的启用 4::我们注册好了后,得申请资源,申请资源是通过第四步,向ResourceScheduler申请的 5:申请并领取资源后,它会找Nodemanager,告诉他我应经申请到了,然后Nodemanager判断一下, 6:知道他申请到了以后就会启动任务,当前启动之前会准备好环境, 7:任务启动以后会跟APplicationmaster进行通信,不断的心跳进行任务的汇报。 8:完成以后会给RM进行汇报,让RSM撤销注册。然后RSM就会回收资源。当然了,我们是分布式的,所以我们不会只跟自己的Nodemanager通信。也会跟其他的节点通信。 8
Shuffle 过程 Shuffle过程是MapReduce的核心,也被称为奇迹发生的地方。要想理解MapReduce, Shuffle是必须要了解的。我看过很多相关的资料,但每次看完都云里雾里的绕着,很难理清大致的逻辑,反而越搅越混。前段时间在做MapReduce job 性能调优的工作,需要深入代码研究MapReduce的运行机制,这才对Shuffle探了个究竟。考虑到之前我在看相关资料而看不懂时很恼火,所以在这里我尽最大的可能试着把Shuffle说清楚,让每一位想了解它原理的朋友都能有所收获。如果你对这篇文章有任何疑问或建议请留言到后面,谢谢! Shuffle的正常意思是洗牌或弄乱,可能大家更熟悉的是Java API里的Collections.shuffle(List)方法,它会随机地打乱参数list里的元素顺序。如果你不知道MapReduce里Shuffle是什么,那么请看这张图: 点击查看原始大小图片 这张是官方对Shuffle过程的描述。但我可以肯定的是,单从这张图你基本不可能明白Shuffle的过程,因为它与事实相差挺多,细节也是错乱的。后面我会具体描述Shuffle的事实情况,所以这里你只要清楚Shuffle的大致范围就成-怎样把map task的输出结果有效地传送到reduce端。也可以这样理解, Shuffle描述着数据从map task输出到reduce task输入的这段过程。 在Hadoop这样的集群环境中,大部分map task与reduce task的执行是在不同的节点上。当然很多情况下Reduce执行时需要跨节点去拉取其它节点上的map task结果。如果集群正在运行的job有很多,那么task的正常执行对集群内部的网络资源消耗会很严重。这种网络消耗是正常的,我们不能限制,能做的就是最大化地减少不必要的消耗。还有在节点内,相比于内存,磁盘IO对job完成时间的影响也是可观的。从最基本的要求来说,我们对Shuffle过程的期望可以有: 完整地从map task端拉取数据到reduce 端。 在跨节点拉取数据时,尽可能地减少对带宽的不必要消耗。 减少磁盘IO对task执行的影响。 OK,看到这里时,大家可以先停下来想想,如果是自己来设计这段Shuffle过程,那么你的设计目标是什么。我想能优化的地方主要在于减少拉取数据的量及尽量使用内存而不是磁盘。 我的分析是基于Hadoop0.21.0的源码,如果与你所认识的Shuffle过程有差别,不吝指出。我会以WordCount为例,并假设它有8个map task和3个reduce task。从上图看出,Shuffle过程横跨map与reduce两端,所以下面我也会分两部分来展开。 先看看map端的情况,如下图: 上图可能是某个map task的运行情况。拿它与官方图的左半边比较,会发现很多不一致。官方图没有清楚地说明partition, sort与combiner到底作用在哪个阶段。我画了这张图,希望让大家清晰地了解从map数据输入到map端所有数据准备好的全过程。 整个流程我分了四步。简单些可以这样说,每个map task都有一个内存缓冲区,存储着map的输出结果,当缓冲区快满的时候需要将缓冲区的数据以一个临时文件的方式存放到磁盘,当整个map task结束后再对磁盘中这个map task产生的所有临时文件做合并,生成最终的正式输出文件,然后等待reduce task来拉数据。相关热词搜索:

我要回帖

 

随机推荐