基于hadoop搜索引擎实践——二级索引文件(五)

基于hadoop搜索引擎——二级索引文件
    一般生成的倒排表文件会比源文件暂用空间大,主要是倒排表文件所记录的信息比较详细。它记录了所有的索引词记录(TERM_RECORD)信息,对于常见的关键词(TERM),其MULTI_INFO可能包含几万甚至几十万个SINGLE_INFO.
    由于倒排表文件很大。系统难以将其在同一时刻全部装入内存;另外一面,用户在查询时只会用到几个TERM及其对应的MULTI_INFO。为了提高查询速度,将倒排文件以Hash表的方式存储在内存中,这样在接受查询TERM的请求时,可以快速返回对应的MULTI_INFO,因此,本系统将倒排表文件划分成若干个字表文件(每个子表文件包含一部分TERM_RECORD),并建立一个描述TERM和其所在子表文件位置的对应关系的索引文件(索引词表)。
1.分割倒排索引文件
    为了保证数据分布的均衡性,在分隔倒排表文件时,精良保证字表文件的大小相差不多。为了达到这一目标,利用MapReduce编程模型具有的2阶段性,完成对倒排表文件的分割。 
    MR程序对数据的处理过程包括Map和Reduce两个阶段。在Map阶段结束后,通过分区(Partition)过程,Mapper发射出来的数据,Partitioner分配至各个Reducer处理。默认情况下,Partitioner将具有相同的key的<key,value>对发送至同一个Reduce函数处理。分割倒排表文件算法的设计思路是改写分布式系统提供的Partitioner函数,令其在洗牌过程中将数据均匀分布给各个Reducer函数,而不是根据key的情况进行分发。Partitiner算法代码如下:
    public class SplitFilePartitioner<K, V> extends Partitioner<K, V> {
    public static int lastID = 0;
    @Override
    public int getPartition(K key, V value, int partitionNum) {
        this.lastID++;
        lastID = (this.lastID % partitionNum);
        return lastID;
    }
}


2.生成二级索引文件
       分割后的倒排字表文件中都互不重复地保存了倒排文件的部分信息。然而,在执行一个查询TERM的命令时,系统并不知道"TERM_RECORD"保存在哪个字表中。因此,需要建立一个索引文件,该文件保存每个TERM与其所在字表(包括在字表中位置)的映射关系,具体格式定义如下:
    (1)索引文件(INDEX_FILE)由若干词及其索引信息组成。每个词及其索引信息是由一个索引词(TERM)和该词的索引信息(INDEX_INFO)组成的,其中TERM和INDEX_INFO之间用空格隔开。索引词记录按照顺序最佳的方式存放,之间用制表符分隔,表示格式如下:
    TERM+'\t'+INDEX_INFO+'\n';
    (2)每个词的索引信息(INDEX_INFO)由子表编号(TABLE_ID),这条索引记录相在该子表中德偏移量(OFFSET)组成,其间用空格隔开。表示如下:
    INDEX_INFO=TABLE_ID+空格+OFFSET
    代码如下:
   
public static class TokenIndexMapper extends
            Mapper<LongWritable, Text, Text, Text> {

        @Override
        protected void map(LongWritable key, Text value, Context context)
                throws IOException, InterruptedException {
            String line = value.toString();
            FileSplit split = (FileSplit) context.getInputSplit();
            context.write(new Text(line.split("\t")[0]), new Text(split
                    .getPath().toString() + " " + key.get()));
        }
    }

    public static class TokenIndexReducer extends
            Reducer<Text, Text, Text, Text> {
        @Override
        protected void reduce(Text key, Iterable<Text> values, Context context)
                throws IOException, InterruptedException {
            boolean flag = true;
            while (values.iterator().hasNext()) {
                if (flag) {
                    context.write(key, values.iterator().next());
                    flag = false;
                }else{
                    values.iterator().next();
                }
            }
        }
    }

    在经过过滤源文件数据,建立倒排表文件,生成二级索引文件等一系列工作之后,整个系统的核心离线工作部分就全部完成了。此后,每当从前台接收到一个TERM查询时,本系统首先从索引文件(INDEX_FILE)中找出这个TERM保存在什么子表的位置(INDEX_INFO);然后打开对应的子表文件并定位相应的位置,读出这个TERM及其对应的MULTI_INFO;最后分析MULTI_INFO中每个SINGLE_INFO的信息,从过滤后的源文件(FlITERED_SOURCE_FILE)中找出相应的帖子信息返回即可。
具体实现代码可以查看:
参考文献:
1.刘鹏,hadoop实战,电子工业出版社,2011.9

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值