您的位置:首页 > 运维架构

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

2014-10-28 17:10 302 查看
基于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)中找出相应的帖子信息返回即可。

具体实现代码可以查看:
离线处理程序:http://download.csdn.net/detail/long1657/8059593
在线处理程序:http://download.csdn.net/detail/long1657/8059567

参考文献:
1.刘鹏,hadoop实战,电子工业出版社,2011.9
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐