19.4.2 即刻Hadoop应用架构

图19-5是即刻搜索引擎的应用架构图。

即刻搜索框架结构比较明了。下面我们对框架各个角色进行介绍。

链接库:这是一个保存了网络中内外部链接的初始数据库,即刻搜索根据数据库中的链接进行网页的爬取。

即刻爬虫:网络爬虫是搜索引擎中必不可少的部分,即刻爬虫根据链接库的内容,爬取网络中的页面资源,形成SSTable并输入HDFS中。SSTable是Google在BigTable设计中提出的一种磁盘文件存储结构,全称是Sorted String Table,以<key, value>对方式在磁盘上存储数据,并根据key的值进行排序,支持随机查找,有不俗的读写性能。

HDFS_Bridge:这是即刻搜索的中间件,为网络爬虫提供写缓存服务,保证爬虫快速写操作。具体来说,通过HDFS_Bridge,爬虫生成的SSTable文件,首先以内存写的速度将数据写入HDFS_Bridge,然后由DFS直接将数据文件写出到DFS磁盘上,这样通过HDFS_Bridge就将SSTable数据的磁盘I/O转化成了内存写,提高了速度。

HDFS:即刻搜索中保存SSTable的分布式文件系统,主要提供海量数据的存储服务,保证数据的安全性和读写服务的可靠性。

MapReduce:这一层主要应用Hadoop中的MapReduce并行编程框架来对爬虫原始数据进行分析,包括PageRank计算、链接分析统计、倒排索引生成等,主要提高了搜索引擎中数据分析步骤的速度,实现了并行化处理。

online-service-cluster:这一层是面向用户的,主要根据用户输入的查询,分析关键词,通过并行框架查找相关结果并返回。

19.4.2 即刻Hadoop应用架构 - 图1

图 19-5 即刻搜索架构图

这里再重点介绍一下MapReduce层。在即刻搜索中,各种基础数据上的操作都是以C++语言编写、经过Hadoop Pipes的封装之后提交给Hadoop执行的,但是具体使用中即刻搜索也从代码层修改了Hadoop Pipes的协议等内容来适应自己的需求。在具体使用中,即刻搜索首先定义了MapReduce框架中的Mapper封装器和Reducer封装器,以Mapper封装器为例,其核心代码如下:


Wrapperclass BasicMapper{

public:

typedef:mapreduce:TaskContextTaskContext;

explicit BasicMapper(){

mapcontext.reset(new MapContext());

}

virtual~BasicMapper(){}

//初始化操作

virtual void OnCreate(TaskContext*context){}

//定义Map阶段

virtual void OnFirstMap(MapContext*context){}

virtual void OnLastMap(MapContext*context){}

virtual void Map(MapContext*context)=0;

……

protected:

//获取输入value

const std:string&GetInputValue(){

return mapcontext->GetInputValue();

}

//获取输入key

const std:string&GetInputkey(){

return mapcontext->GetInputKey();

}

//反序列化

template<typenameT>

boolValueToThrift(T*object){

return mapcontext->ValueToThrift(object);

}

……

DISALLOW_COPY_AND_ASSIGN(BasicMapper);

}


利用这些封装器作为基类,编写自己的MapReduce框架代码就非常方便。下面就是一个简单的例子:


class SampleMap:public BasicMapper{//Mapper

public:

virtual~SampleMap(){}

virtual void Map(mapreduce:MapContext*context)

{

string key=GetInputKey();

string value=GetInputValue();

Object obj_val;

ValueToThrift(&obj_val);//反序列化

……

context->Emit(key, newvalue);//输出

}

};

class SampleRed:public BasicReducer{

public:

virtual void Reduce(mapreduce:MapContext*context){

string key=GetInputKey();

while(NextValue()){

string value=GetInputValue();

……

}

context->Emit(key, newvalue);//输出

}

};


可以看出:上面的代码同用Java语言编写的代码非常类似。除了上面的主体Mapper和Reducer代码之外,再定义好其他作业信息就可以提交给Hadoop Pipes来运行了。