亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Hadoop 的 TotalOrderPartitioner

系統 2566 0
http://blog.oddfoo.net/2011/04/17/mapreduce-partition%E5%88%86%E6%9E%90-2/

Partition所處的位置


Partition位置

Partition主要作用就是將map的結果發送到相應的reduce。這就對partition有兩個要求:

1)均衡負載,盡量的將工作均勻的分配給不同的reduce。

2)效率,分配速度一定要快。

Mapreduce提供的Partitioner


Mapreduce默認的partitioner是HashPartitioner。除了這個mapreduce還提供了3種partitioner。如下圖所示:

patition類結構


1. Partitioner 是partitioner的基類,如果需要定制partitioner也需要繼承該類。

2. HashPartitioner是mapreduce的默認partitioner。計算方法是

which reducer=(key.hashCode() & Integer.MAX_VALUE) % numReduceTasks,得到當前的目的reducer。

3. BinaryPatitioner繼承于Partitioner< BinaryComparable ,V>,是Partitioner的偏特化子類。該類提供leftOffset和rightOffset,在計算which reducer時僅對鍵值K的[rightOffset,leftOffset]這個區間取hash。

Which reducer=(hash & Integer.MAX_VALUE) % numReduceTasks

4. KeyFieldBasedPartitioner也是基于hash的個partitioner。和BinaryPatitioner不同,它提供了多個區間用于計算hash。當區間數為0時KeyFieldBasedPartitioner退化成HashPartitioner。

5. TotalOrderPartitioner這個類可以實現輸出的全排序。不同于以上3個partitioner,這個類并不是基于hash的。在下一節里詳細的介紹totalorderpartitioner。

TotalOrderPartitioner


每一個reducer的輸出在默認的情況下都是有順序的,但是reducer之間在輸入是無序的情況下也是無序的。如果要實現輸出是全排序的那就會用到TotalOrderPartitioner。

要使用TotalOrderPartitioner,得給TotalOrderPartitioner提供一個partition file。這個文件要求Key (這些key就是所謂的劃分)的數量和當前reducer的數量-1相同并且是從小到大排列。對于為什么要用到這樣一個文件,以及這個文件的具體細節待會還會提到。

TotalOrderPartitioner對不同Key的數據類型提供了兩種方案:

1) 對于非BinaryComparable(參考附錄A)類型的Key,TotalOrderPartitioner采用二分發查找當前的K所在的index。

例如reducer的數量為5,partition file 提供的4個劃分為【2,4,6,8】。如果當前的一個key value pair 是<4,”good”>利用二分法查找到index=1,index+1=2那么這個key value pair將會發送到第二個reducer。如果一個key value pair為<4.5, “good”>那么二分法查找將返回-3,同樣對-3加1然后取反就是這個key value pair 將要去的reducer。

對于一些數值型的數據來說,利用二分法查找復雜度是o(log (reducer count)),速度比較快。

2) 對于BinaryComparable類型的Key(也可以直接理解為字符串)。字符串按照字典順序也是可以進行排序的。這樣的話也可以給定一些劃分,讓不同的字符串key分配到不同的reducer里。這里的處理和數值類型的比較相近。

例如reducer的數量為5,partition file 提供了4個劃分為【“abc”, “bce”, “eaa”, ”fhc”】那么“ab”這個字符串將會被分配到第一個reducer里,因為它小于第一個劃分“abc”。

但是不同于數值型的數據,字符串的查找和比較不能按照數值型數據的比較方法。mapreducer采用的Tire tree的字符串查找方法。查找的時間復雜度o(m),m為樹的深度,空間復雜度o(255^m-1)。是一個典型的空間換時間的案例。

Tire Tree


Tire tree的構建

假設樹的最大深度為3,劃分為【aaad ,aaaf, aaaeh,abbx 】

tairtree結構


Mapreduce里的Tire tree主要有兩種節點組成:
1) Innertirenode
Innertirenode在mapreduce中是包含了255個字符的一個比較長的串。上圖中的例子只包含了26個英文字母。
2) 葉子節點{unslipttirenode, singesplittirenode, leaftirenode}
Unslipttirenode 是不包含劃分的葉子節點。
Singlesplittirenode 是只包含了一個劃分點的葉子節點。
Leafnode是包含了多個劃分點的葉子節點。(這種情況比較少見,達到樹的最大深度才出現這種情況。在實際操作過程中比較少見)

Tire tree的搜索過程

接上面的例子:
1)假如當前 key value pair這時會找到圖中的leafnode,在leafnode內部使用二分法繼續查找找到返回 aad在 劃分數組中的索引。找不到會返回一個和它最接近的劃分的索引。
2)假如找到singlenode,如果和singlenode的劃分相同或小返回他的索引,比singlenode的劃分大則返回索引+1。
3)假如找到nosplitnode則返回前面的索引。如將會返回abbx的在劃分數組中的索引。

TotalOrderPartitioner的疑問

上面介紹了partitioner有兩個要求,一個是速度另外一個是均衡負載。使用tire tree提高了搜素的速度,但是我們怎么才能找到這樣的partition file 呢?讓所有的劃分剛好就能實現均衡負載。

InputSampler
輸入采樣類,可以對輸入目錄下的數據進行采樣。提供了3種采樣方法。

采樣類結構圖

采樣方式對比表:

類名稱

采樣方式

構造方法

效率

特點

SplitSampler<K,V>

對前n個記錄進行采樣

采樣總數,劃分數

最高

RandomSampler<K,V>

遍歷所有數據,隨機采樣

采樣頻率,采樣總數,劃分數

最低

IntervalSampler<K,V>

固定間隔采樣

采樣頻率,劃分數

對有序的數據十分適用

writePartitionFile這個方法很關鍵,這個方法就是根據采樣類提供的樣本,首先進行排序,然后選定(隨機的方法)和reducer數目-1的樣本寫入到partition file。這樣經過采樣的數據生成的劃分,在每個劃分區間里的key value pair 就近似相同了,這樣就能完成均衡負載的作用。

TotalOrderPartitioner實例


    
public class SortByTemperatureUsingTotalOrderPartitioner extends Configured implements Tool { @Override public int run(String[]args) throws Exception { JobConfconf=JobBuilder.parseInputAndOutput( this ,getConf(),args); if (conf== null ){ return -1; } conf.setInputFormat(SequenceFileInputFormat. class ); conf.setOutputKeyClass(IntWritable. class ); conf.setOutputFormat(SequenceFileOutputFormat. class ); SequenceFileOutputFormat.setCompressOutput(conf, true ); SequenceFileOutputFormat .setOutputCompressorClass(conf,GzipCodec. class ); SequenceFileOutputFormat.setOutputCompressionType(conf, CompressionType.BLOCK); conf.setPartitionerClass(TotalOrderPartitioner. class ); InputSampler.Sampler<IntWritable,Text>sampler= new InputSampler.RandomSampler<IntWritable,Text>( 0.1,10000,10); Pathinput=FileInputFormat.getInputPaths(conf)[0]; input=input.makeQualified(input.getFileSystem(conf)); PathpartitionFile= new Path(input,"_partitions"); TotalOrderPartitioner.setPartitionFile(conf,partitionFile); InputSampler.writePartitionFile(conf,sampler); // AddtoDistributedCache URIpartitionUri= new URI(partitionFile.toString()+"#_partitions"); DistributedCache.addCacheFile(partitionUri,conf); DistributedCache.createSymlink(conf); JobClient.runJob(conf); return 0; } public static void main(String[]args) throws Exception{ int exitCode=ToolRunner.run( new SortByTemperatureUsingTotalOrderPartitioner(),args); System.exit(exitCode); } }

示例程序引用于:http://www.cnblogs.com/funnydavid/archive/2010/11/24/1886974.html

附錄A
Text 為BinaryComparable,WriteableComparable類型。
BooleanWritable、ByteWritable、DoubleWritable、MD5hash、IntWritable、FloatWritable、LongWritable、NullWriable等都為WriteableComparable。

http://www.cnblogs.com/OnlyXP/archive/2008/12/06/1349026.html

在0.19.0以前的版本中,Hadoop自身并沒有提供全排序的solution,如果使用缺省的partitioner(HashPartitioner)每個reducer的輸出自身是有序的,但是多個reducer的輸出文件之間不存在全序的關系;如果想實現全排序,需要自己實現Partitioner,比如針對key為Mac地址的Partitioner,如假定Mac地址的分布是均勻的,可以根據Mac地址的前兩個字節構造不超過255個reducer的Partitioner;但是這種Partitoiner是應用邏輯相關的,因此沒有通用性,為此Hadoop 0.19.0提供了一個通用的全序Partitioner。

TotalOrderPartitioner最初用于 Hadoop Terasort ,也許是考慮到其通用性,后來作為0.19.0的release feature發布。

Partitioner的目的是決定每一個Map輸出的Record由哪個Reducer來處理,它必須盡可能滿足
1. 平均分布。即每個Reducer處理的Record數量應該盡可能相等。

2. 高效。由于每個Record在Map Reduce過程中都需要由Partitioner分配,它的效率至關重要,需要使用高效的算法實現。
獲取數據的分布

對于第一點,由于TotalOrderPartitioner 事先并不知道key的分布,因此需要通過少量數據sample估算key的分布,然后根據分布構造針對的Partition模型。

0.19.0中有一個InputSampler就是做這個事情的,
通過指定Reducer個數, 并讀取一部分的輸入數據作為sample,將sample數據排序并根據Reducer個數等分后,得到每個Reducer處理的區間。比如包含9條數據的sample,其排好序的key分別為:
a b c d e f g h i
如果指定Reducer個數為3,每個Reducer對應的區間為

Reducer0 [a, b, c]
Reducer1 [d, e, f]
Reducer2 [g, h, i]

區間之間的邊界稱為Cut Point ,上面三個Reducer的Cut point為 d, g InputSampler將這cut points排序并寫入HDFS文件,這個文件即包含了輸入數據的分布規律。

根據分布構建高效Partition模型

對于上面提到的第2點,高效性,
在讀取數據的分布規律文件之后,TotalOrderPartitioner會判斷key是不是BinaryComparable類型的。

BinaryComparable的含義是“字節可比的”,o.a.h.io.Text就是一個這樣的類型,因為兩個Text對象可以按字節比較,如果對應的字節不相等就立刻可以判斷兩個Text的大小。

先說不是
BinaryComparable 類型的情況,這時 TotalOrderPartitioner會使用二分查找BinarySearch來確定key屬于哪個區間,進而確定屬于哪個Reducer,每一次查找的時間復雜度為O(logR),R為Reducer的個數。

如果key是
BinaryComparable類型, TotalOrderPartitioner會根據 cut points構造 Trie Trie 是一種更為高效的用于查找的數據結構, 這種數據結構適合key為字符串類型,如下圖

TotalOrderPartitioner中的Trie缺省 深度為2,即使用2+1個prefix構造Trie;每個父節點有255個子節點,對應255個ASCII字符。查找的時間復雜度為O(m),m為樹的深度,空間復雜度為O(255 m-1 ),可以看到,這是一種空間換時間的方案,當樹深度為2時,可以最多分配255 * 255個reducer,這在絕大情況下足夠了。

可以看到,使用
Trie進行Partition的效率高于binarySearch,單次執行兩種查找可能不會有 什么感覺,但是當處理億計的Record時,他們的差距就明顯了。

Hadoop 的 TotalOrderPartitioner


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 国产亚洲免费观看 | 久久草在线视频播放 | 天天爽天天干 | 亚洲国产成人99精品激情在线 | 亚洲国产欧美在线观看 | 久久狠狠第一麻豆婷婷天天 | 九九这里有精品 | 天天操天天草 | 成人欧美在线观看免费视频 | 中文乱码精品一区二区三区 | 国产2021久久精品 | 亚洲自拍第二页 | 久久中文字幕在线 | 97久久曰曰久久久 | 久久大香伊蕉在人线国产昨爱 | 天天爱天天色天天干 | 香蕉成人在线视频 | 国产成a人亚洲精v品久久网 | 欧美一区二区三区成人看不卡 | 特黄女一级毛片 | 亚洲天堂久久新 | 欧美在线成人免费国产 | 奇米线在人线免费视频 | 97久久人人爽人人爽人人 | 久久www免费人成看国产片 | 一 级 黄 色蝶 片 | 国产精品久久久久久久久免费 | 九九热九九热 | 久久久这里只有免费精品2018 | 国产色视频一区 | 免费在线观看黄色的网站 | 成人a毛片 | 久久伦理片 | 91九色精品国产免费 | 日本免费一级视频 | 欧美色欧美亚洲高清在线视频 | 色婷婷综合久久久 | 日本高清中文字幕一区二区三区 | 欧美亚洲国产精品久久高清 | 国产精品久久久久一区二区 | 欧美体内she精视频毛片 |