1. 程式人生 > >【Hadoop基礎教程】9、Hadoop之倒排索引

【Hadoop基礎教程】9、Hadoop之倒排索引

開發環境

硬體環境:Centos 6.5 伺服器4臺(一臺為Master節點,三臺為Slave節點)
軟體環境:Java 1.7.0_45、hadoop-1.2.1

1、倒排索引

倒排索引是文件檢索系統中最常用的資料結構,被廣泛用於全文搜尋引擎。它主要是用來儲存某個單詞(或片語)在一個文件或一組文件的儲存位置的對映,即提供了一種根據內容來查詢文件的方式。由於不是根據文件來確定文件所包含的內容,而是進行了相反的操作(根據關鍵字來查詢文件),因而稱為倒排索引(Inverted Index)。通常情況下,倒排索引由一個單詞(片語)以及相關的文件列表(標示文件的ID號,或者是指定文件所在位置的URI)組成,如下圖所示:

 倒排索引結構

從上圖可以看出,單詞1出現在{文件1、文件4、文件13、……}中,單詞2出現在{文件3、文件5、文件15、…..}中,而單詞3出現在{文件1、文件8、文件20、….}中,還需要給每個文件新增一個權值,用來指出每個文件與搜素內容相關的相關度,如下圖所示:

 新增權重的倒排索引

最常用的是使用詞頻作為權重,即記錄單詞在文件中出現的次數了。以英文為例,如下圖所示,索引檔案中的“MapReduce”一行表示:“MapReduce”這個單詞在文字T0中出現過1次,T1中出現過1次,T2中出現過2次。當搜尋條件為“MapReduce”、“is”、“simple”時,對應的集合為:{T0,T1,T2}∩{ T0,T1}∩{ T0,T1}={ T0,T1},即文字T0和T1包含所要索引的單詞,而且只有T0是連續的。

 新增權重的倒排索引

2、Map過程

首先使用預設的TextInputFormat類對輸入檔案進行處理,得到文字中每行的偏移量及其內容。顯然,Map過程首先必須分析輸入的< key,value>對,得到倒排索引中需要的三個資訊:單詞、文件URI和詞頻,如下圖所示。這裡存在兩個問題:第一,< key,value>對只能有兩個值,在不使用Hadoop自定義資料型別的情況下,需要根據情況將其中兩個值合併成一個值,作為key或value值;第二,通過一個Reduce過程無法同時完成詞頻統計和文件列表,所以必須增加一個Combine過程完成詞頻統計。

 map過程

這裡將單詞和URI組成Key值(如“MapReduce :1.txt”),將詞頻作為value,這樣做的好處是可以利用MapReduce框架自帶的Map端排序,將同一文件的相同單詞的詞頻組成列表,傳遞給Combine過程,實現類似於WordCount的功能。
Map過程核心程式碼實現如下,詳細原始碼請參考:InvertedIndex\src\com\zonesion\hdfs\InvertedIndex.java。

public static class InvertedIndexMapper extends 
    Mapper<Object,Text,Object,Text>{
    private Text keyInfo = new Text();//儲存單詞和URI的組合
    private  Text valueInfo = new Text();//儲存詞頻
    private FileSplit split;//儲存Split物件
    @Override
    public void map(Object key, Text value, Context context)
            throws IOException, InterruptedException {
        split = (FileSplit)context.getInputSplit();
        StringTokenizer itr = new StringTokenizer(value.toString());
        while(itr.hasMoreTokens()){
            //key值由單詞和URI組成
            keyInfo.set(itr.nextToken()+":"+split.getPath().toString());
            valueInfo.set("1");
            context.write(keyInfo, valueInfo);//輸出:<key,value>---<"MapReduce:1.txt",1>
        }
    }
}

3、Combine過程

經過map方法處理之後,Combine過程將key值相同的value值累加,得到一個單詞在文件中的詞頻,如下圖所示。如果直接將Map的輸出結果作為Reduce過程的輸入,在Shuffle過程時將面臨一個問題:所有具有相同單詞的記錄(由單詞、URI和詞頻組成)應該交由同一個Reduce處理,但當前key值無法保證這一點,所以必須修改key值和value值。這次將單詞作為key值,URI和詞頻作為value值。這樣做的好處是可以利用MapReduce框架預設的HashPartitioner類完成Shuffle過程,將相同單詞的所有記錄傳送給同一個Reducer處理。

 combine過程

Combine過程核心程式碼實現如下,詳細原始碼請參考:InvertedIndex\src\com\zonesion\hdfs\InvertedIndex.java。

public static class InvertedIndexCombiner 
    extends Reducer<Text, Text, Text, Text>{
    private Text info = new Text();
    @Override
    protected void reduce(Text key, Iterable<Text> values,Context context)
            throws IOException, InterruptedException {
        //輸入:<key,value>---<"MapReduce:1.txt",list(1,1,1,1)>
        int sum = 0;
        for(Text value : values){
            sum += Integer.parseInt(value.toString());
        }
        int splitIndex = key.toString().indexOf(":");
        info.set(key.toString().substring(splitIndex+1)+":"+sum);
        key.set(key.toString().substring(0,splitIndex));
        context.write(key, info);//輸出:<key,value>----<"Mapreduce","0.txt:2">
    }
}

4、Reduce過程

經過上述兩個過程後,Reduce過程只需要將相同key值的value值組合成倒排索引檔案所需的格式即可,剩下的事情就可以直接交給MapReduce框架處理了,如下圖所示。

 reduce過程

Reduce過程核心程式碼實現如下,詳細原始碼請參考:InvertedIndex\src\com\zonesion\hdfs\InvertedIndex.java。

public static class InvertedIndexReducer 
    extends Reducer<Text, Text, Text, Text>{
    private Text result = new Text();
    @Override
    protected void reduce(Text key, Iterable<Text> values,Context context)
            throws IOException, InterruptedException {
        //輸入:<"MapReduce",list("0.txt:1","1.txt:1","2.txt:1")>
        String fileList = new String();
        for(Text value : values){//value="0.txt:1"
            fileList += value.toString()+";";
        }
        result.set(fileList);
        context.write(key, result);//輸出:<"MapReduce","0.txt:1,1.txt:1,2.txt:1">
    }
}

5、驅動實現

驅動核心程式碼實現如下,詳細原始碼請參考:InvertedIndex\src\com\zonesion\hdfs\InvertedIndex.java。

public static void main(String[] args) throws Exception {
    Configuration conf = new Configuration();
    String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
    if (otherArgs.length != 2) {
      System.err.println("Usage: InvertedIndex <in> <out>");
      System.exit(2);
    }
    Job job = new Job(conf, "InvertedIndex");
    job.setJarByClass(InvertedIndex.class);
    //設定Mapper類、Combiner類、Reducer類;
    job.setMapperClass(InvertedIndexMapper.class);
    job.setCombinerClass(InvertedIndexCombiner.class);
    job.setReducerClass(InvertedIndexReducer.class);
    //設定了Map過程和Reduce過程的輸出型別,設定key、value的輸出型別為Text;
    job.setOutputKeyClass(Text.class);
    job.setOutputValueClass(Text.class);
    //設定任務資料的輸入、輸出路徑;
    FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
    FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
    //執行job任務,執行成功後退出;
    System.exit(job.waitForCompletion(true) ? 0 : 1);
}

6、部署執行

1)啟動Hadoop叢集

[[email protected] CompanyJoinAddress]$ start-dfs.sh
[hado[email protected] CompanyJoinAddress]$ start-mapred.sh
[[email protected] CompanyJoinAddress]$ jps
5283 SecondaryNameNode
5445 JobTracker
5578 Jps
5109 NameNode

2)部署原始碼

#設定工作環境
[[email protected] ~]$ mkdir -p /usr/hadoop/workspace/MapReduce
#部署原始碼
將InvertedIndex資料夾拷貝到/usr/hadoop/workspace/MapReduce/ 路徑下;

3)編譯檔案

#切換工作目錄
[[email protected] ~]$ cd /usr/hadoop/workspace/MapReduce/InvertedIndex
#編譯檔案
[[email protected] InvertedIndex]$ javac -classpath /usr/hadoop/hadoop-core-1.2.1.jar:/usr/hadoop/lib/commons-cli-1.2.jar -d bin src/com/zonesion/hdfs/InvertedIndex.java
[[email protected] InvertedIndex]$ ls bin/com/zonesion/hdfs/ -la
總用量 20
drwxrwxr-x 2 hadoop hadoop 4096 9月  18 17:09 .
drwxrwxr-x 3 hadoop hadoop   17 9月  18 17:09 ..
-rw-rw-r-- 1 hadoop hadoop 1982 9月  18 17:09 InvertedIndex.class
-rw-rw-r-- 1 hadoop hadoop 2173 9月  18 17:09 InvertedIndex$InvertedIndexCombiner.class
-rw-rw-r-- 1 hadoop hadoop 2103 9月  18 17:09 InvertedIndex$InvertedIndexMapper.class
-rw-rw-r-- 1 hadoop hadoop 1931 9月  18 17:09 InvertedIndex$InvertedIndexReducer.class

4)打包jar檔案

[[email protected] InvertedIndex]$ jar -cvf InvertedIndex.jar -C bin/ .
已新增清單
正在新增: com/(輸入 = 0) (輸出 = 0)(儲存了 0%)
正在新增: com/zonesion/(輸入 = 0) (輸出 = 0)(儲存了 0%)
正在新增: com/zonesion/hdfs/(輸入 = 0) (輸出 = 0)(儲存了 0%)
正在新增: com/zonesion/hdfs/InvertedIndex$InvertedIndexMapper.class(輸入 = 2103) (輸出 = 921)(壓縮了 56%)
正在新增: com/zonesion/hdfs/InvertedIndex$InvertedIndexCombiner.class(輸入 = 2173) (輸出 = 944)(壓縮了 56%)
正在新增: com/zonesion/hdfs/InvertedIndex$InvertedIndexReducer.class(輸入 = 1931) (輸出 = 830)(壓縮了 57%)
正在新增: com/zonesion/hdfs/InvertedIndex.class(輸入 = 1982) (輸出 = 1002)(壓縮了 49%)

5)上傳輸入檔案

#建立InvertedIndex/input/輸入資料夾
[[email protected] InvertedIndex]$ hadoop fs -mkdir InvertedIndex/input/
#上傳檔案到InvertedIndex/input/輸入資料夾
[[email protected] InvertedIndex]$ hadoop fs -put input/*.txt /user/hadoop/InvertedIndex/input
#驗證上傳檔案是否成功
[[email protected] InvertedIndex]$ hadoop fs -ls /user/hadoop/InvertedIndex/input
Found 3 items
-rw-r--r--   1 hadoop supergroup 20 2014-09-18 17:12 /user/hadoop/InvertedIndex/input/0.txt
-rw-r--r--   1 hadoop supergroup 32 2014-09-18 17:12 /user/hadoop/InvertedIndex/input/1.txt
-rw-r--r--   1 hadoop supergroup 30 2014-09-18 17:12 /user/hadoop/InvertedIndex/input/2.txt

6)執行Jar檔案

[[email protected] InvertedIndex]$ hadoop jar InvertedIndex.jar com.zonesion.hdfs.InvertedIndex InvertedIndex/input InvertedIndex/output
14/09/18 17:16:40 INFO input.FileInputFormat: Total input paths to process : 3
14/09/18 17:16:40 INFO util.NativeCodeLoader: Loaded the native-hadoop library
14/09/18 17:16:40 WARN snappy.LoadSnappy: Snappy native library not loaded
14/09/18 17:16:41 INFO mapred.JobClient: Running job: job_201409150922_0003
14/09/18 17:16:42 INFO mapred.JobClient:  map 0% reduce 0%
14/09/18 17:16:45 INFO mapred.JobClient:  map 100% reduce 0%
14/09/18 17:16:51 INFO mapred.JobClient:  map 100% reduce 33%
14/09/18 17:16:53 INFO mapred.JobClient:  map 100% reduce 100%
14/09/18 17:16:53 INFO mapred.JobClient: Job complete: job_201409150922_0003
14/09/18 17:16:53 INFO mapred.JobClient: Counters: 29
......

7)檢視輸出結果

#檢視HDFS上output目錄內容
[[email protected] InvertedIndex]$ hadoop fs -ls /user/hadoop/InvertedIndex/output
Found 3 items
-rw-r--r--   1 hadoop supergroup  0 2014-07-21 15:31 /user/hadoop/InvertedIndex/output/_SUCCESS
drwxr-xr-x   - hadoop supergroup  0 2014-07-21 15:30 /user/hadoop/InvertedIndex/output/_logs
-rw-r--r--   1 hadoop supergroup665 2014-07-21 15:31 /user/hadoop/InvertedIndex/output/part-r-00000
#檢視結果輸出檔案內容
[[email protected] InvertedIndex]$ hadoop fs -cat /user/hadoop/InvertedIndex/output/part-r-00000
Hello           hdfs://Master:9000/user/hadoop/InvertedIndex/input/2.txt:1;
MapReduce   hdfs://Master:9000/user/hadoop/InvertedIndex/input/2.txt:2;hdfs://Master:9000/user/hadoop/InvertedIndex/input/1.txt:1;hdfs://Master:9000/user/hadoop/InvertedIndex/input/0.txt:1;
Powerful    hdfs://Master:9000/user/hadoop/InvertedIndex/input/1.txt:1;
bye         hdfs://Master:9000/user/hadoop/InvertedIndex/input/2.txt:1;
is          hdfs://Master:9000/user/hadoop/InvertedIndex/input/0.txt:1;hdfs://Master:9000/user/hadoop/InvertedIndex/input/1.txt:2;
simple      hdfs://Master:9000/user/hadoop/InvertedIndex/input/1.txt:1;hdfs://Master:9000/user/hadoop/InvertedIndex/input/0.txt:1;

您可能喜歡

相關推薦

Hadoop基礎教程9Hadoop索引

開發環境 硬體環境:Centos 6.5 伺服器4臺(一臺為Master節點,三臺為Slave節點) 軟體環境:Java 1.7.0_45、hadoop-1.2.1 1、倒排索引 倒排索引是文件檢索系統中最常用的資料結構,被廣泛用於全文搜尋引

Hadoop基礎教程1Hadoop伺服器基礎環境搭建

本blog以K-Master伺服器基礎環境配置為例分別演示使用者配置、sudo許可權配置、網路配置、關閉防火牆、安裝JDK工具等。使用者需參照以下步驟完成KVMSlave1~KVMSlave3伺服器的基礎環境配置。 開發環境 硬體環境:Centos

HBase基礎教程1HBase單機模式與偽分布式模式安裝(轉)

service 4.2 zookeepe .tar.gz class href base mem 創建 在這篇blog中,我們將介紹Hbase的單機模式安裝與偽分布式的安裝方式,以及通過瀏覽器查看Hbase的用戶界面。搭建hbase偽分布式環境的前提是我們已經搭建好了had

HBase基礎教程1HBase單機模式與偽分散式模式安裝

在這篇blog中,我們將介紹Hbase的單機模式安裝與偽分散式的安裝方式,以及通過瀏覽器檢視Hbase的使用者介面。搭建hbase偽分散式環境的前提是我們已經搭建好了hadoop完全分散式環境,搭建hadoop環境請參考:【Hadoop基礎教程】4、Hadoop

HBase基礎教程5HBase API訪問

開發環境 硬體環境:Centos 6.5 伺服器4臺(一臺為Master節點,三臺為Slave節點) 軟體環境:Java 1.7.0_45、Eclipse Juno Service Release 2、hadoop-1.2.1、hbase-0.94.20

Unity3D基礎教程給初學者看的Unity教程(零):如何學習Unity3D

cos 詳解 component lock index unity3d遊戲 design 技術棧 log 【Unity3D基礎教程】給初學者看的Unity教程(零):如何學習Unity3D http://www.cnblogs.com/neverdie/p/How_To_

zabbix系列教程用戶自定義監控

系統用戶 新建 mct 運用 systemctl 一個 start shell 教程 本篇介紹運用zabbix進行自定義監控,以系統用戶登錄數量為例。 一、zabbix自定義語法 UserParameter=<key>,<shell command

劍指offer9用兩個棧實現隊列

題目 壓入 () ack 用兩個棧 nbsp del emp span 題目 用兩個棧實現隊列。隊列聲明如下,實現appendTail和deleteHead,分別完成在隊列尾部插入節點,和頭部刪除節點的功能。 思路 尾部插入:直接向stack1壓入即可 頭部刪除:先進先出,

Hadoop基礎教程-第2章 Hadoop快速入門(2.2 Hadoop下載與安裝)

2.1 Hadoop下載與安裝2.1.1 官網下載可以使用迅雷或QQ旋風等多執行緒下載工具來下載,支援斷點續傳。成功下載後得到hadoop-2.7.3.tar.gz壓縮檔案,204M。請檢查壓縮包是否204M,瀏覽器下載的話可能會中斷。2.1.2 上傳至虛擬機器通過ll或ls命令可以檢視到已經上傳到虛擬機器n

Arduino基礎教程LCD5110顯示屏

Nokia 5110顯示屏模組 準備材料 Arduino UNO *1 Nokia 5110 LCD *1 跳線 若干 接線 Nokia 511

Unity3D基礎教程給初學者看的Unity教程(六):理解Unity的新GUI系統(UGUI)

理解UGUI的基礎架構 UGUI是Unity在4.6中引入的新的GUI系統,與傳統的中介軟體NGUI相比,這套新GUI系統有幾個核心亮點: 放棄了Atlas的概念,使用Packing Tag的方式來進行圖集的規劃 放棄了depth來確定UI顯示層級的概念,使用Hierarchy的SiblingIndex

Unity3D基礎教程給初學者看的Unity教程(二):所有指令碼元件的基類 -- MonoBehaviour的前世今生

引子 上一次我們講了GameObject,Compoent,Time,Input,Physics,其中Time,Input,Physics都是Unity中的全域性變數。GameObject是遊戲中的基本物件。GameObject是由Component組合而成的,GameObject本身必須有

Unity3D基礎教程給初學者看的Unity教程(五):詳解Unity3D中的協程(Coroutine)

為什麼需要協程 在遊戲中有許多過程(Process)需要花費多個邏輯幀去計算。 你會遇到“密集”的流程,比如說尋路,尋路計算量非常大,所以我們通常會把它分割到不同的邏輯幀去進行計算,以免影響遊戲的幀率。 你會遇到“稀疏”的流程,比如說遊戲中的觸發器,這種觸發器大多數時候什麼也不做,但

Unity3D基礎教程給初學者看的Unity教程(三):通過製作Flappy Bird瞭解Native 2D中的Sprite,Animation

引子 上一次我們講了MonoBehaviour的前世今生,瞭解了遊戲中的每一個GameObjec都是由指令碼控制的,這一次我們開始將Unity中Native 2D中的Sprite,並且使用Animation來讓Sprite動起來。 在接下來的幾篇部落格裡,我會通過做一個Flappy Bird來講解

Unity3D基礎教程給初學者看的Unity教程(四):通過製作Flappy Bird瞭解Native 2D中的RigidBody2D和Collider2D

引子 認識RigidBody 當RigidBody2D的質量屬性被設定為0時,剛體的質量變為無限大,此時剛體相當於靜態剛體,永遠一動不動。但是在Unity中你是無法把一個RigidBody2D的質量設定為0的,所以,當你想建立一個靜態剛體時,只需要建立碰撞器,而不需要建立RigidBo

Unity3D基礎教程給初學者看的Unity教程(七):在Unity中構建健壯的單例模式(Singleton)

該部落格中的程式碼均出自我的開源專案 : 迷你微信 為什麼需要單例模式 遊戲中需要單例有以下幾個原因: 我們需要在遊戲開始前和結束前做一些操作,比如網路的連結和斷開,資源的載入和解除安裝,我們一般會把這部分邏輯放在單例裡。 單例可以控制初始化和銷燬順序,而靜態變數和場景中的GameObject都無法控制

Unity3D基礎教程給初學者看的Unity教程(一):GameObject,Compoent,Time,Input,Physics

Unity3D重要模組的類圖 最近剛剛完成了一個我個人比較滿意的小專案:【深入Cocos2d-x】使用MVC架構搭建遊戲Four,在這個遊戲中,我使用了自己搭建的MVC架構來製作一個遊戲,做到了比較好的SoC(關注點分離)。但是苦於Cocos2d-x沒有一個比較完善的編輯器,所以我開始學習另一個非常流行

View基礎知識View的滑動scrollToscrollBy

本系列文章部分摘自《Android開發藝術探索》,目的是提取精幹知識點加上自己部分理解作為備忘筆記,如有侵權請及時聯絡我,再次感謝作者,如喜歡請支援購買作者正版書籍 目錄 View的滑動方式 View 的滑動主要通過三種方式實現: 通

UiBot基礎教程變量與常量 - 定義變量以及變量類型

換行 變量名 ges 整數 ESS oss asc 布爾型 式表 UiBot中的變量是動態類型的,無需再定義的時候聲明變量的類型,即變量的值和類型都可以在運行過程中動態改變。這也符合一般腳本語言如Python、Lua、JavaScript的習慣。 定義變量名的方式是:Dim

Hadoop基礎教程-第2章 Hadoop快速入門(2.4 Hadoop單機執行)

第2章 Hadoop快速入門2.4 Hadoop單機執行緊接上一節內容,首先切換到Hadoop根目錄 或者cd /opt/hadoop-2.7.3進入Hadoop根目錄 通過pwd命令可以知道當前所在目錄[root@node1 hadoop-2.7.3]# pwd注意:本節命令都將在/opt/hadoop-2