??xml version="1.0" encoding="utf-8" standalone="yes"?>
]]>
]]>
ZKFC是自动故障{UM的另一个新lgQ是ZooKeeper的客LQ也监视和管理NameNode的状态。每个运行NameNode的主Zq行了一个ZKFCq程QZKFC负责Q?/p>
在典型部|中QZooKeeper守护q程q行在三个或者五个节点上Q但׃ZooKeeper本n需要较的资源Q所以将ZooKeeper部v在与现役NameNode和待机NameNode相同的主ZQ还可以ZooKeeper部vCYARN的ResourceManager相同的节点上。徏议配|ZooKeeper数据存储在与HDFS元数据不同的盘上以得到最好的性能和隔L。在配置自动故障转移之前需要先停掉集群Q目前在集群q行时还不可能将手动故障转移的安装{换ؓ自动故障转移的安装。接下来看看如何配置HA的自动故障{UR首先在hdfs-site.xml中添加下面的参数Q该参数的值默认ؓfalseQ?/p>
在core-site.xml文g中添加下面的参数Q该参数的gؓZooKeeper服务器的地址QZKFC用该地址?/p>
在HA或者HDFS联盟中,上面的两个参数还需要以NameServiceID为后~Q比如dfs.ha.automatic-failover.enabled.mycluster。除了上面的两个参数外,q有其它几个参数用于自动故障转移Q比如ha.zookeeper.session-timeout.msQ但对于大多数安装来说都不是必须的?/p>
在添加了上述的配|参数后Q下一步就是在ZooKeeper中初始化要求的状态,可以在Q一NameNode中运行下面的命o实现该目的,该命令将在ZooKeeper中创建znodeQ?/p>
在启用自动故障{Uȝ集群中,start-dfs.sh脚本在Mq行NameNode的主Z自动启动ZKFC守护q程Q一旦ZKFC启动完毕Q它们将自动选择一个NameNode为现役NameNode。如果手动管理集中的服务,需要在每台q行NameNode的主Z手动启动ZKFCQ命令ؓQ?/p>
如果正在q行一个安全的集群Q可能想保存储在ZooKeeper中的信息也是安全的,q将L恶意的客L修改ZooKeeper中的元数据或者潜在地触发一个错误的故障转移。ؓ了保护ZooKeeper中的信息Q首先在core-site.xml中添加下面的参数Q?/p>
参数g的@字符表示参数g存在@后的盘文g中。第一个配|文件指定了ZooKeeper的认证列表,其格式与ZK CLI使用的相同,例如Qdigest:hdfs-zkfcs:mypasswordQ其中hdfs-zkfcs为ZooKeeper的用户名Qmypassword为密码。其ơ用下面的命o认证生成一个ZooKeeper讉K控制列表Q?/p>
拯->之后的字W串q添加digest:前缀Q然后粘贴到zk-acls.txt中,例如Qdigest:hdfs-zkfcs:vlUvLnd8MlacsE80rDuu6ONESbM=:rwcda。要想ACLs生效Q需要再ơ运行zkfc –formatZK。最后可能像下面q样在ZK CLI中验证ACLsQ?/p>
在安装完成自动故障{UdQ或讔R?a title="软g试知识? target="_blank" style="color: #df3434; text-decoration: none; font-weight: bold;">试一下。首先定位现役NameNodeQ可以通过讉KNameNode的web面来确定哪个NameNode是active状态的。一旦确定了处于active状态的NameNodeQ就需要在该节点上刉点故障Q比如用命令kill -9 <pid of NN>模拟JVM崩溃Q或重启L或拔掉网U来模拟不同的中断。一旦触发了自动故障转移Q另一个NameNode应该自动在几U钟内变为active状态。检到故障q触发故障{Uȝ参数ha.zookeeper.session-timeout.ms控制Q该参数Zcore-site.xml中,默认?U。如果测试不成功Q可能是配置问题Q检查ZKFC和NameNodeq程的日志以q一步诊断问题,通常错误都是很明昄?/p>
在Yarn中有三种调度器可以选择Q?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">FIFO Scheduler Q?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">Capacity SchedulerQ?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">FairS cheduler?/p>
FIFO Scheduler
把应用按提交的顺序排成一个队列,q是一个先q先出队列,在进行资源分配的时候,先给队列中最头上的应用进行分配资源,待最头上的应用需求满_再给下一个分配,以此cL?/p>
FIFO Scheduler
是最单也是最Ҏ理解的调度器Q也不需要Q何配|,但它q不适用于共享集。大的应用可能会占用所有集资源,q就D其它应用被阻塞。在׃n集群中,更适合采用Capacity Scheduler
?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">Fair SchedulerQ这两个调度器都允许大Q务和Q务在提交的同时获得一定的pȝ资源?/p>
下面“Yarn调度器对比图”展示了这几个调度器的区别Q从图中可以看出Q在FIFO 调度器中Q小d会被大Q务阻塞?/p>
而对于Capacity调度器,有一个专门的队列用来q行Q务,但是为小d专门讄一个队列会预先占用一定的集群资源Q这导致大d的执行时间会落后于用FIFO调度器时的时间?/p>
在Fair调度器中Q我们不需要预先占用一定的pȝ资源QFair调度器会为所有运行的job动态的调整pȝ资源。如下图所C,当第一个大job提交Ӟ只有q一个job在运行,此时它获得了所有集资源;当第二个Q务提交后QFair调度器会分配一半资源给q个Q务,让这两个d公^的共享集资源?/p>
需要注意的是,在下图Fair调度器中Q从W二个Q务提交到获得资源会有一定的延迟Q因为它需要等待第一个Q务释攑֍用的Container。小d执行完成之后也会释放自己占用的资源,大Q务又获得了全部的pȝ资源。最l的效果是Fair调度器即得到了高的资源利用率又能保证Q务及时完成?/p>
Yarn调度器对比图:
Capacity 调度器允许多个组l共享整个集,每个l织可以获得集群的一部分计算能力。通过为每个组l分配专门的队列Q然后再为每个队列分配一定的集群资源Q这h个集就可以通过讄多个队列的方式给多个l织提供服务了。除此之外,队列内部又可以垂直划分,q样一个组l内部的多个成员可以共享这个队列资源了Q在一个队列内部,资源的调度是采用的是先进先出(FIFO){略?/p>
通过上面那幅图,我们已经知道一个job可能使用不了整个队列的资源。然而如果这个队列中q行多个jobQ如果这个队列的资源够用Q那么就分配l这些jobQ如果这个队列的资源不够用了呢?其实Capacity调度器仍可能分配额外的资源给q个队列Q这是“Ҏ队?#8221;(queue elasticity)的概c?/p>
在正常的操作中,Capacity调度器不会强刉放ContainerQ当一个队列资源不够用Ӟq个队列只能获得其它队列释放后的Container资源。当Ӟ我们可以为队列设|一个最大资源用量Q以免这个队列过多的占用I闲资源Q导致其它队列无法用这些空闲资源,q就?#8221;Ҏ队?#8221;需要权衡的地方?/p>
假设我们有如下层ơ的队列Q?/p>
root ├── prod └── dev ├── eng └── science
下面是一个简单的Capacity调度器的配置文gQ文件名?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">capacity-scheduler.xml。在q个配置中,在root队列下面定义了两个子队列prod
?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">devQ分别占40%?0%的容量。需要注意,一个队列的配置是通过属?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">yarn.sheduler.capacity.<queue-path>.<sub-property>指定的,<queue-path>
代表的是队列的承树Q如root.prod
队列Q?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;"><sub-property>一般指capacity
?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">maximum-capacity?/p>
我们可以看到Q?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">dev队列又被分成?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">eng?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">science两个相同定w的子队列?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">dev?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">maximum-capacity属性被讄成了75%Q所以即?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">prod队列完全I闲dev
也不会占用全部集资源,也就是说Q?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">prod队列仍有25%的可用资源用来应急。我们注意到Q?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">eng?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">science两个队列没有讄maximum-capacity
属性,也就是说eng
?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">science队列中的job可能会用到整?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">dev队列的所有资源(最多ؓ集群?5%Q。而类似的Q?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">prod׃没有讄maximum-capacity属性,它有可能会占用集全部资源?/p>
Capacity容器除了可以配置队列及其定w外,我们q可以配|一个用h应用可以分配的最大资源数量、可以同时运行多应用、队列的ACL认证{?/p>
关于队列的设|,q取决于我们具体的应用。比如,在MapReduce中,我们可以通过mapreduce.job.queuename
属性指定要用的队列。如果队列不存在Q我们在提交d时就会收到错误。如果我们没有定义Q何队列,所有的应用会攑֜一?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">default队列中?/p>
注意Q对于Capacity调度器,我们的队列名必须是队列树中的最后一部分Q如果我们用队列树则不会被识别。比如,在上面配|中Q我们?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">prod?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">eng作ؓ队列名是可以的,但是如果我们?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">root.dev.eng或?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">dev.eng是无效的?/p>
Fair调度器的设计目标是ؓ所有的应用分配公^的资源(对公q的定义可以通过参数来设|)。在上面?em style="padding: 0px;">“Yarn调度器对比图”展示了一个队列中两个应用的公q度;当然Q公q度在也可以在多个队列间工作。D个例子,假设有两个用户A和BQ他们分别拥有一个队列。当A启动一个job而B没有dӞA会获得全部集资源;当B启动一个job后,A的job会l运行,不过一会儿之后两个d会各自获得一半的集群资源。如果此时B再启动第二个jobq且其它jobq在q行Q则它将会和B的第一个job׃nBq个队列的资源,也就是B的两个job会用于四分之一的集资源,而A的job仍然用于集群一半的资源Q结果就是资源最l在两个用户之间q等的共享。过E如下图所C:
调度器的使用是通过yarn-site.xml
配置文g中的yarn.resourcemanager.scheduler.class
参数q行配置的,默认采用Capacity Scheduler调度器。如果我们要使用Fair调度器,需要在q个参数上配|FairSchedulercȝ全限定名Q?nbsp;org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler
?/p>
Fair调度器的配置文g位于c\径下?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">fair-scheduler.xml文g中,q个路径可以通过yarn.scheduler.fair.allocation.file
属性进行修攏V若没有q个配置文gQFair调度器采用的分配{略Q这个策略和3.1节介l的cMQ调度器会在用户提交W一个应用时为其自动创徏一个队列,队列的名字就是用户名Q所有的应用都会被分配到相应的用户队列中?/p>
我们可以在配|文件中配置每一个队列,q且可以像Capacity 调度器一样分层次配置队列。比如,参?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">capacity-scheduler.xml来配|fair-schedulerQ?nbsp;
队列的层ơ是通过嵌套<queue>
元素实现的。所有的队列都是root
队列的孩子,即我们没有配到<root>
元素里。在q个配置中,我们?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">dev队列有分成了eng
?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">science两个队列?/p>
Fair调度器中的队列有一个权重属性(q个权重是对公q的定义Q,q把q个属性作为公q度的依据。在q个例子中,当调度器分配集群40:60
资源l?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">prod?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">dev时便视作公^Q?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">eng?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">science队列没有定义权重Q则会被q_分配。这里的权重q不是百分比Q我们把上面?0?0分别替换??Q效果也是一L。注意,对于在没有配|文件时按用戯动创建的队列Q它们仍有权重ƈ且权重gؓ1?/p>
每个队列内部仍可以有不同的调度策略。队列的默认调度{略可以通过元素<defaultQueueSchedulingPolicy>
q行配置Q如果没有配|,默认采用公^调度?/p>
管是Fair调度器,其仍支持在队列别进行FIFO调度。每个队列的调度{略可以被其内部?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;"><schedulingPolicy> 元素覆盖Q在上面q个例子中,prod
队列p指定采用FIFOq行调度Q所以,对于提交?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">prod队列的Q务就可以按照FIFO规则序的执行了。需要注意,prod
?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">dev之间的调度仍然是公^调度Q同?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">eng?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">science也是公^调度?/p>
管上面的配|中没有展示Q每个队列仍可配|最大、最资源占用数和最大可q行的应用的数量?/p>
Fair调度器采用了一套基于规则的pȝ来确定应用应该放到哪个队列。在上面的例子中Q?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;"><queuePlacementPolicy> 元素定义了一个规则列表,其中的每个规则会被逐个试直到匚w成功。例如,上例W一个规?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">specifiedQ则会把应用攑ֈ它指定的队列中,若这个应用没有指定队列名或队列名不存在,则说明不匚wq个规则Q然后尝试下一个规则?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">primaryGroup规则会尝试把应用攑֜?em style="padding: 0px;">用户所在的Unixl名命名的队列中Q如果没有这个队列,不创建队列{而尝试下一个规则。当前面所有规则不满Ӟ则触?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">default规则Q把应用攑֜dev.eng
队列中?/p>
当然Q我们可以不配置queuePlacementPolicy
规则Q调度器则默认采用如下规则:
<queuePlacementPolicy> <rule name="specified" /> <rule name="user" /> </queuePlacementPolicy>
上面规则可以归结成一句话Q除非队列被准确的定义,否则会以用户名ؓ队列名创建队列?/p>
q有一个简单的配置{略可以使得所有的应用攑օ同一个队列(defaultQ,q样可以让所有应用之间^{共享集而不是在用户之间。这个配|的定义如下Q?/p>
<queuePlacementPolicy> <rule name="default" /> </queuePlacementPolicy>
实现上面功能我们q可以不使用配置文gQ直接设|?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">yarn.scheduler.fair.user-as-default-queue=falseQ这样应用便会被攑օdefault 队列Q而不是各个用户名队列。另外,我们q可以设|?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">yarn.scheduler.fair.allow-undeclared-pools=falseQ这L户就无法创徏队列了?/p>
当一个job提交C个繁忙集中的空队列Ӟjobq不会马上执行,而是d直到正在q行的job释放pȝ资源。ؓ了提交job的执行时间更具预性(可以讄{待的超时时_QFair调度器支持抢占?/p>
抢占是允许调度器杀掉占用超q其应占份额资源队列的containersQ这些containers资源便可被分配到应该享有q些份额资源的队列中。需要注意抢占会降低集群的执行效率,因ؓ被终止的containers需要被重新执行?/p>
可以通过讄一个全局的参?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">yarn.scheduler.fair.preemption=true来启用抢占功能。此外,q有两个参数用来控制抢占的过期时_q两个参数默认没有配|,需要至配|一个来允许抢占ContainerQ:
- minimum share preemption timeout - fair share preemption timeout
如果队列?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;">minimum share preemption timeout指定的时间内未获得最的资源保障Q调度器׃抢占containers。我们可以通过配置文g中的元素<defaultMinSharePreemptionTimeout>
为所有队列配|这个超时时_我们q可以在<queue>
元素内配|?code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;"><minSharePreemptionTimeout>元素来ؓ某个队列指定时旉?/p>
与之cMQ如果队列在fair share preemption timeout
指定旉内未获得q等的资源的一半(q个比例可以配置Q,调度器则会进行抢占containers。这个超时时间可以通过元素<defaultFairSharePreemptionTimeout>
和元素元素<fairSharePreemptionTimeout>
分别配置所有队列和某个队列的超时时间。上面提到的比例可以通过<defaultFairSharePreemptionThreshold>
(配置所有队??code style="font-family: Arial, Helvetica, sans-serif; padding: 0px;"><fairSharePreemptionThreshold>(配置某个队列)q行配置Q默认是0.5?/p>
关键?/strong> | 情Ş | 后果 |
Join | 其中一个表较小Q?/p> 但是key集中 | 分发到某一个或几个Reduce上的数据q高于^均?/p> |
大表与大表,但是分桶的判断字D?值或ID?/p> | q些I值都׃个reduce处理Q灰常慢 | |
group by | group by l度q小Q?/p> 某值的数量q多 | 处理某值的reduce灰常耗时 |
Count Distinct | 某特DD?/p> | 处理此特D值的reduce耗时 |
1)、key分布不均匀
2)、业务数据本w的Ҏ?/p>
3)、徏表时考虑不周
4)、某些SQL语句本n有数据倾斜
dq度长时间维持在99%Q或100%Q,查看d监控面Q发现只有少量(1个或几个Qreduce子Q务未完成。因为其处理的数据量和其他reduce差异q大?/p>
单一reduce的记录数与^均记录数差异q大Q通常可能辑ֈ3倍甚x多?最长时长远大于q_旉?/p>
hive.map.aggr=true
Map 端部分聚合,相当于Combiner
hive.groupby.skewindata=true
有数据倾斜的时候进行负载均衡,当选项讑֮?trueQ生成的查询计划会有两个 MR Job。第一?MR Job 中,Map 的输出结果集合会随机分布?Reduce 中,每个 Reduce 做部分聚合操作,q输出结果,q样处理的结果是相同?Group By Key 有可能被分发C同的 Reduce 中,从而达到负载均衡的目的Q第二个 MR Job 再根据预处理的数据结果按?Group By Key 分布?Reduce 中(q个q程可以保证相同?Group By Key 被分布到同一?Reduce 中)Q最后完成最l的聚合操作?/p>
如何JoinQ?/strong>
关于驱动表的选取Q选用join key分布最均匀的表作ؓ驱动?/p>
做好列裁剪和filter操作Q以辑ֈ两表做join的时候,数据量相对变的效果?/p>
大小?/strong>JoinQ?/strong>
使用map join让小的维度表Q?000条以下的记录条数Q?先进内存。在map端完成reduce.
大表Join大表Q?/strong>
把空值的key变成一个字W串加上随机敎ͼ把倾斜的数据分C同的reduce上,׃null值关联不上,处理后ƈ不媄响最l结果?/p>
count distinct大量相同Ҏ?/strong>
count distinctӞgؓI的情况单独处理Q如果是计算count distinctQ可以不用处理,直接qoQ在最后结果中?。如果还有其他计,需要进行group byQ可以先gؓI的记录单独处理Q再和其他计结果进行union?/p>
group byl度q小Q?/strong>
采用sum() group by的方式来替换count(distinct)完成计算?/p>
Ҏ情况Ҏ处理Q?/strong>
在业务逻辑优化效果的不大情况下Q有些时候是可以倾斜的数据单独拿出来处理。最后union回去?/p>
场景Q?/strong>如日志中Q常会有信息丢失的问题,比如日志中的 user_idQ如果取其中?user_id ?用户表中的user_id 兌Q会到数据倾斜的问题?/p> 解决Ҏ1Q?/strong> user_id为空的不参与兌Q红色字体ؓ修改后) 解决Ҏ2 Q?/strong>赋与I值分新的key?/p> l论Q?/strong>Ҏ2比方?效率更好Q不但io了Q而且作业C了。解x??logd两次Qjobs?。解x? job数是1 。这个优化适合无效 id (比如 -99 , ’’, null {? 产生的倾斜问题。把I值的 key 变成一个字W串加上随机敎ͼp把倾斜的数据分C同的reduce?,解决数据倾斜问题?/p> 场景Q?/strong>用户表中user_id字段为intQlog表中user_id字段既有stringcd也有intcd。当按照user_idq行两个表的Join操作Ӟ默认的Hash操作会按int型的id来进行分配,q样会导致所有stringcdid的记录都分配C个Reducer中?/p> 解决ҎQ?/strong>把数字类型{换成字符串类?/p> 使用 map join 解决表(记录数少)兌大表的数据倾斜问题Q这个方法用的频率非常高,但如果小表很大,大到map join会出现bug或异常,q时需要特别的处理?nbsp;以下例子: users 表有 600w+ 的记录,?users 分发到所有的 map 上也是个不小的开销Q而且 map join 不支持这么大的小表。如果用普通的 joinQ又会碰到数据倾斜的问题?/p> 解决ҎQ?/strong> 假如Qlog里user_id有上百万个,q就又回到原来map join问题。所q,每日的会员uv不会太多Q有交易的会员不会太多,有点ȝ会员不会太多Q有佣金的会员不会太多等{。所以这个方法能解决很多场景下的数据倾斜问题?/p> 使map的输出数据更均匀的分布到reduce中去Q是我们的最l目标。由于Hash法的局限性,按key Hash会或多或的造成数据倾斜。大量经验表明数据倾斜的原因是Zؓ的徏表疏忽或业务逻辑可以规避的。在此给为通用的步骤: 1、采样log表,哪些user_id比较倾斜Q得C个结果表tmp1。由于对计算框架来说Q所有的数据q来Q他都是不知道数据分布情늚Q所以采hq不可少的?/p> 2、数据的分布W合C会学统计规则,贫富不均。倾斜的key不会太多Q就像一个社会的富h不多Q奇特的Z多一栗所以tmp1记录C很少。把tmp1和users做map join生成tmp2,把tmp2ddistribute file cache。这是一个mapq程?/p> 3、mapdusers和logQ假如记录来自log,则检查user_id是否在tmp2里,如果是,输出到本地文件a,否则生成<user_id,value>的key,value对,假如记录来自member,生成<user_id,value>的key,value对,q入reduce阶段?/p> 4、最l把a文gQ把Stage3 reduce阶段输出的文件合qv写到hdfs?/p> 如果认业务需要这样倾斜的逻辑Q考虑以下的优化方案: 1、对于joinQ在判断表不大?G的情况下Q用map join 2、对于group by或distinctQ设?nbsp;hive.groupby.skewindata=true 3、尽量用上q的SQL语句调节q行优化select * from log a join users b on a.user_id is not null and a.user_id = b.user_id union all select * from log a where a.user_id is null;
select * from log a left outer join users b on case when a.user_id is null then concat(‘hive’,rand() ) else a.user_id end = b.user_id;
3.2不同数据cd兌产生数据倾斜
select * from users a left outer join logs b on a.usr_id = cast(b.user_id as string)
3.3表不小不大Q怎么?map join 解决倾斜问题
select * from log a left outer join users b on a.user_id = b.user_id;
select /*+mapjoin(x)*/* from log a
left outer join (
select /*+mapjoin(c)*/d.* from (
select distinct user_id from log ) c join users d
on c.user_id = d.user_id ) x
on a.user_id = b.user_id; 4ȝ
]]>
Hive背后的Mapper调优:
1,Mapper数过?会生大量小文g,׃Mapper是基于虚拟机?q多的Mapper创徏和初始化及关闭虚拟机都会消耗大量的g资源;
Mapper数太?q发度过?Job执行旉q长,无法充分利用分布式硬件资?
2,Mapper数据׃么决定呢?
输入文g数目;
输入文g的大?
配置参数;
默认情况?例如一个文?00M,BLock大小?28M,那么Mapper数目是7?6个Mapper处理的数据是 128M, 1个Mapper处理的数据是32M;再例?一个目录下有三个文件分别大问5M 10M 150M
此时会?个Mapper,处理的数据分别是5M 10M 128M 22M;
减少Mapper的个?p合ƈ文?q种文件有可能是直接来自于数据源的文?也可能是Reducer产生的小文g;
set hive.input.format=org.apache.Hadoop.hive.ql.io.CombineHiveInputFormat;
set hive.merge.mapFiles=true;
set hive.merge.mapredFiles=true;
set hive.merge.size.per.task=256000000
set mapred.max.split.size=256000000
set mapred.min.split.size.per.node=128000000
增加Mapper的个?一般是通过控制Hive SQL中上一个Job的Reducer个数来控制的,例如在Join操作的时候会把多个表分解为多个Job;
set mapred.map.tasks=2;
set hive.merge.mapFiles=true;
set hive.merge.mapredFiles=true;
set hive.merge.size.per.task=256000000
例如我们??00M的文?按照上面的配|会产生10个Mapper,5个Mapper处理的都?56M的数?另外5个Mapper处理的都?4M的数?问题?大的Mapper会数据倾斜
如何解决,讄set mapred.map.tasks=6,此时ҎMapRed的运行机?会划?个Mapper,每个Mapper的处理数据的大小?50M, min(1500M/6, 256M) =250M
Hive背后的Reducer调优:
1,Reducer数目q大的话,会生很多小文g,每个Reducer都会产生一个文?如果q些文件是下一个JOB的输?则会需要对文件进行合q?同样启动 初始化和销毁Reducer的虚拟机也需要消耗大量的g;
Reducer数据q小的话,Reduce的时间会比较?也可能会出现数据倾斜;
2,如何控制Reducer的个数呢?
set hive.exec.reducers.byte.per.reducer=1G
set hive.exec.reducers.max=999
Reducer个数=min(999, Reducer的数据输入总量/1G);
set mapred.reduce.tasks = 10, 默认?; 如果说当前的Reducer的结果很?且被接下来多个Job使用其结?我们该如何设|参数呢?一般都需要调大该参数;
什么情况下只有一个Reducer?如果不进行Group by但却需要汇?或者说Order by,当然如果最后Reducer的数据小于默认的1G的话,也会只有一个Reducer;
1,Hive在分布式q行的时候最x的是数据倾斜,q是׃分布式系l的Ҏ决定的,因ؓ分布式系l之所以很快是׃作业q_分配l了不同的节?不同节点同心协力,从而达到更快处理完作业的目?
Z说明一?处理数据倾斜的能力是hadoop?a title="Apache Spark知识? target="_blank" style="text-decoration: none; color: #df3434; font-weight: bold;">Spark工程师最核心的竞争力之一;
2,Hive中数据倾斜的原?
数据在分布式节点上分布不q;
join时某些key可能特别?
groupBy的时候某个Key可能特别?
count(distinct)有可能出现数据倾斜,因ؓ其内部首先会q行groupBy操作;
3,join,我们希望join时候key是分?如果一个key的数据量特别?有可能会出现数据倾斜和OOM,一个核心点?表join大表,在reduce阶段左侧的小表会加蝲q内?减少OOM的风?
4,大表join大表的情?数据倾斜,例如null?解决办法一般是要打散null?例如说用随机数{?如果数据倾斜比较严重,采用q种方式可以提升臛_一倍的速度;
5,mapJoin:表join(?大表的时?可以采用mapJoin的方式把表全部加蝲到Mapper端的内存?*+MAPJOIN(table_name)*/;
6,表join(?大表的时?是否会自动进行mapJoin,惌行mapJoin,需要设|?set hive.auto.convert.join=true,Hive在进行join的时候会判断左表的大来军_是否q行mapJoin:
set hive.mapjoin.smalltable.filesize=128000000;
set hive.mapjoin.cache.numrows=100000;
上述参数可以Ҏ实际的硬件机器的内存q行调整,Ҏ能有至关重要的影响,因ؓ没有了Shuffle;
对于mapJoin我们能够使用Mapper端JVM中多大的内存?
set hive.mapjoin.followby.gby.localtask.max.momery.usage = 0.8
set hive.mapjoin.localtask.max.memory.uage=0.9
7,groupBy,我们可以讄在Mapper端进行部分聚?最后在Reducer端进行全局聚合
set hive.map.aggr=true;
set hive.groupby.mapaggr.checkinterval=100000
set hive.groupby.skewindata = true 内部会生两个Job,W一个Job会通过自己?a title="法与数据结构知识库" target="_blank" style="text-decoration: none; color: #df3434; font-weight: bold;">法打散倾斜的Keyq进行聚合操作且保留l果,W二个Job会完成全部的groupBy操作,会生Mapper-Reducer-Reducer的结?br data-filtered="filtered" />
8, count(distinct),如果某个字段特别?Ҏ产生数据倾斜,解决思\:
在查询语句中例如对nullq行qo,在结果中?
9, W卡积:join时候没有on条g,或者on条g无效,q个时候会使用Reducerq行W卡积的操?
Apache Hive是一个构建在Hadoop基础设施之上的数据仓库。通过Hive可以使用HQL语言查询存放在HDFS上的数据。HQL是一U类SQL语言Q这U语a最l被转化为Map/Reduce. 虽然Hive提供了SQL查询功能Q但是Hive不能够进行交互查?-因ؓ它只能够在Haoop上批量的执行Hadoop?/p>
Apache HBase是一UKey/ValuepȝQ它q行在HDFS之上。和Hive不一PHbase的能够在它的数据库上实时q行Q而不是运行MapReduced。Hive被分Zؓ表格Q表格又被进一步分割ؓ列簇。列必M用schema定义Q列将某一cd列集合v来(列不要求schema定义Q。例如,“message”列簇可能包含Q?#8220;to”, ”from” “date”, “subject”, ?#8221;body”. 每一?key/value对在Hbase中被定义Z个cellQ每一个key由row-keyQ列、列和时间戳。在Hbase中,行是key/value映射的集合,q个映射通过row-key来唯一标识。Hbase利用Hadoop的基设施Q可以利用通用的设备进行水q的扩展?/p>
2. 两者的特点
Hive帮助熟悉SQL的hq行MapReduced。因为它是JDBC兼容的,同时Q它也能够和现存的SQL工具整合在一赗运行Hive查询会花费很长时_因ؓ它会默认遍历表中所有的数据。虽然有q样的缺点,一ơ遍历的数据量可以通过Hive的分区机制来控制。分区允许在数据集上q行qo查询Q这些数据集存储在不同的文g夹内Q查询的时候只遍历指定文g夹(分区Q中的数据。这U机制可以用来,例如Q只处理在某一个时间范围内的文Ӟ只要q些文g名中包括了时间格式?/p>
HBase通过存储key/value来工作。它支持四种主要的操作:增加或者更新行Q查看一个范围内的cellQ获取指定的行,删除指定的行、列或者是列的版本。版本信息用来获取历史数据(每一行的历史数据可以被删除,然后通过Hbase compactions可以释攑ևI间Q。虽然HBase包括表格Q但是schema仅仅被表格和列簇所要求Q列不需要schema。Hbase的表格包括增?计数功能?/p>
3. 限制
Hive目前不支持更新操作。另外,׃hive在hadoop上运行批量操作,它需要花费很长的旉Q通常是几分钟到几个小时才可以获取到查询的l果。Hive必须提供预先定义好的schema文件和目录映射到列Qƈ且Hive与ACID不兼宏V?/p>
HBase查询是通过特定的语a来编写的Q这U语a需要重新学习。类SQL的功能可以通过Apache Phonenix实现Q但q是以必L供schemaZL。另外,Hbase也ƈ不是兼容所有的ACIDҎ,虽然它支持某些特性。最后但不是最重要?-Zq行HbaseQ?font style="padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; padding-right: 0px" color="#0000ff">Zookeeper是必ȝQzookeeper是一个用来进行分布式协调的服务,q些服务包括配置服务Q维护元信息和命名空间服务?/p>
4. 应用场景
Hive适合用来对一D|间内的数据进行分析查询,例如Q用来计趋势或者网站的日志。Hive不应该用来进行实时的查询。因为它需要很长时间才可以q回l果?/p>
Hbase非常适合用来q行大数据的实时查询。Facebook用Hbaseq行消息和实时的分析。它也可以用来统计Facebook的连接数?/p>
5. ȝ
Hive和Hbase是两U基于Hadoop的不同技?-Hive是一U类SQL的引擎,q且q行MapReducedQHbase是一U在Hadoop之上的NoSQL 的Key/vale数据库。当Ӟq两U工h可以同时使用的。就像用Google来搜索,用FaceBookq行C交一PHive可以用来q行l计查询QHBase可以用来q行实时查询Q数据也可以从Hive写到HbaseQ设|再从Hbase写回Hive?/p>
UDP(User Datagram Protocol)
UDP不提供复杂的控制机制Q利用IP提供面向无连接的通信服务。ƈ且它是将应用E序发来的数据在收到的那一刻,立刻按照原样发送到|络上的一U机制?/span>
即是出现网l拥늚情况下,UDP也无法进行流量控制等避免|络拥塞的行为。此外,传输途中如果出现了丢包,UDO也不负责重发。甚臛_出现包的到达序乱掉时也没有U正的功能。如果需要这些细节控Ӟ那么不得不交l由采用UDO的应用程序去处理。换句话_UDP部分控制{Ud应用E序d理,自己却只提供作ؓ传输层协议的最基本功能。UDP有点cM于用戯什么听什么的机制Q但是需要用户充分考虑好上层协议类型ƈ制作相应的应用程序?/span>
TCP(Transmission Control Protocol)
TCP充分实现爱呢了数据传输时各种控制功能Q可以进行丢包的重发控制Q还可以Ҏ序ؕ掉的分包q行序控制。而这些在UDP中都没有。此外,TCP作ؓ一U面向有q接的协议,只有在确认通信对端存在时才会发送数据,从而可以控刉信量的浪贏V?/span>
TCP通过验和、序列号、确认应{、重发控制、连接管理以及窗口控制等机制实现可靠性传输。此处不一一叙述?/span>
TCP与UDP如何加以区分使用Q?/span>
TCP用于在传输层有必要实现可靠性传输的情况。由于它是面向有q接q具备顺序控制、重发控制等机制的。所以它可以为应用提供可靠传输?/span>
另一斚wQUDP主要用于那些寚w速传输和实时性有较高要求的通信或广播通信。D一个IP电话q行通话的例子。如果用TCPQ数据在传送途中如果丢失会被重发Q但是这h法流畅地传输通话人的声音Q会D无法q行正常交流。而采用UDPQ它不会q行重发处理。从而也׃会有声音大幅度gq到辄问题。即使有部分数据丢失Q也只是影响某一部分的通话。此外,在多播与q播通信中也使用UDP而不是UDP。RIP、DHCP{基于广播的协议也要依赖于UDP?/span>
TCP与UDP区别ȝQ?/strong>
1、TCP面向q接Q如打电话要先拨号徏立连接);UDP是无q接的,卛_送数据之前不需要徏立连?/span>
2、TCP提供可靠的服务。也是_通过TCPq接传送的数据Q无差错Q不丢失Q不重复Q且按序到达;UDP最大努力交付,即不保证可靠交付6、TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信?/span>
UDP如何实现可靠传输
׃在传输层UDP已经是不可靠的连接,那就要在应用层自己实C些保障可靠传输的机制
单来Ԍ要用UDP来构建可靠的面向q接的数据传输,p实现cM于TCP协议?/span>
时重传Q定时器Q?/span>
有序接受 Q添加包序号Q?/span>
应答认 QSeq/Ack应答机制Q?/span>
滑动H口量控制{机?Q滑动窗口协议)
{于说要在传输层的上一层(或者直接在应用层)实现TCP协议的可靠数据传输机Ӟ比如使用UDP数据?序列PUDP数据?旉戳等Ҏ?/span>
目前已经有一些实现UDP可靠传输的机Ӟ比如
1、什么是Hbase?/p>
?/span>一个高可靠性、高性能、列存储、可伸羃、实时读写的分布?a title="MySQL知识? class="replace_word" style="text-decoration: none; font-weight: bold; color: rgb(223,52,52)" target="_blank">数据?/a>pȝ?/span>
适合于存储非l构?/span>数据Q基于列的而不是基于行的模?/span>
如图Q?a title="Hadoop知识? class="replace_word" style="text-decoration: none; font-weight: bold; color: rgb(223,52,52)" target="_blank">Hadoop生态中hbase与其他部分的关系?br />
2、关pL据库已经行很多q_q且hadoop已经有了HDFS和MapReduceQؓ什么需要HBase?
1、模型概q?/p>
?/span> |
?/span> |
[“201505003”,“Info”,“email”, 1174184619081] |
“xie@qq.com” |
[“201505003”,“Info”,“email”, 1174184620720] |
“you@163.com” |
4、物理视?br />
三、HBase实现原理
1?span style="color: black">HBase
的实现包括三个主要的功能lgQ?/span>客户端访问数据时?#8220;三d”
Z加速寻址Q客L会缓存位|信息,同时Q需要解决缓存失效问?/span>
3、HBase的三层结构中各层ơ的名称和作?/span>
层次 |
名称 |
作用 |
W一?/span> |
Zookeper文g |
记录?/span>-ROOT-表的位置信息 |
W二?/span> |
-ROOT-?/span> |
记录?/span>.META.表的Region位置信息 -ROOT-表只能有一?/span>Region。通过-ROOT-表,可以访?/span>.META.表中的数?/span> |
W三?/span> |
.META.?/span> |
记录了用h据表?/span>Region位置信息Q?/span>.META.表可以有多个RegionQ保存了HBase中所有用h据表?/span>Region位置信息 |
行键是按?/span>字典?/span>存储Q因此,设计行键Ӟ要充分利用这个排序特点,经怸赯取的数据存储C块,最q可能会被访问的数据攑֜一块?/span>
举个例子Q如果最q写?/span>HBase表中的数据是最可能被访问的Q可以考虑时间戳作ؓ行键的一部分Q由于是字典序排序,所以可以?/span>Long.MAX_VALUE- timestamp作ؓ行键Q这栯保证新写入的数据在读取时可以被快速命中?/span>
InMemoryQ创的时候,可以通过HColumnDescriptor.setInMemory(true)表攑ֈRegion服务器的~存中,保证在读取的时候被cache命中?/span>
Max VersionQ创的时候,可以通过HColumnDescriptor.setMaxVersions(int maxVersions)讄表中数据的最大版本,如果只需要保存最新版本的数据Q那么可以设|?/span>setMaxVersions(1)?/span>
Time To Live创徏表的时候,可以通过HColumnDescriptor.setTimeToLive(inttimeToLive)讄表中数据的存储生命期Q过期数据将自动被删除,例如如果只需要存储最q两天的数据Q那么可以设|?/span>setTimeToLive(2* 24 * 60 * 60)?/span>
易用,减少~码
4、HBase只有一个针对行健的索引
讉KHBase表中的行Q只有三U方式: