1. 程式人生 > >mapreduce對key值排序問題

mapreduce對key值排序問題

 最近在學習MapReduce程式設計遇到很多用MR實現按某一列值排序,或二次排序的類似問題,於是試著用MR實現各種排序問題,最終有點小總結:無需在key物件之外寫任何排序函式,MR會完成按key值排序,具體詳解如下:

  在這之前要先說一下WritableComparable介面。Writable介面大家可能都知道,它是一個實現了序列化協議的序列化物件。在Hadoop中定義一個結構化物件都要實現Writable介面,使得該結構化物件可以序列化為位元組流,位元組流也可以反序列化為結構化物件。那WritableComparable介面可序列化並且可比較的介面。MapReduce中所有的key值型別都必須實現這個介面,既然是可序列化的那就必須得實現readFiels()

write()這兩個序列化和反序列化函式,既然也是可比較的那就必須得實現compareTo()函式,該函式即是比較和排序規則的實現。這樣MR中的key值就既能可序列化又是可比較的。下面幾符圖是API中對WritableComparable介面的解釋及其方法,還有一個實現了該介面的物件的列子:

                                                                        圖 一 WritableComparable 介面解釋

                                                                     圖 二 WritableComparable 介面方法

                                                              圖 三 自定義物件實現WritableComparable 介面例子

  從圖三可以看到自定義的物件實現WritableComparable介面除了實現readFields和write方法之外,還必須得實現compareTo()方法,這也是key值排序的關鍵,實現了改方法key值之間是可比較可排序的,所以也不用另外寫排序函數了。Hadoop提供的資料型別如Text,IntWritable,LongWritable,DoubleWritable和FloatWritable等也都實現了WritableComparable介面。所以我們最開始寫wordcount等例子,我們使用Longritable,Text等型別做key值並沒有去實現compareTo函式,最後結果也是排序好的,就是因為Hadoop提供的資料型別已經實現了WC介面,已經實現了compareTo函數了。如果你有特殊要求,Text,IntWritable這些型別不能滿足你對key值的要求,需要自己新建一個數據物件作為自己的key值型別,那就像上圖 圖三那樣重寫一個類實現WritableComparable介面,同時實現compareTo函式,函式內部實現你自己的排序規則,最後reduce的資料就會按key值排序了。

     所以總結上面,hadoop會呼叫key值型別的compareTo函式按照該函式的要求對key值進行排序。所以你想對哪些列排序就要把哪些列併入到key值物件中,像二次排序那樣,要對兩列進行排序,兩列值都要併入key中,則key成為包含兩個屬性的複合key,Hadoop 提供的key值可用的型別不能滿足要求,那就重寫一個物件實現WritableComparable介面(類圖三),該物件包含連個屬性,並實現compareTo函式,最後會根據key值對兩列資料排序,從而實現二次排序。本人也層試圖用MR實現對value的排序,最終沒能成功,也可能是本人水平有限,但至少會比對key排序複雜,這也是我要強調的不要試圖單純的對value進行排序,否則比較難實現排序。