您的位置:首页 > 其它

lucene的分布式搜索-入门篇

2012-08-22 09:09 295 查看
我的废话:

前些日子客户对以前网站搜索功能不太满意,因为用户输入关键字进行查询时要再选择对应的分类栏目,用户体验不是很到位。所以找我们对他的网站提供全文检索的功能,跟搜索引擎类似输入一组关键字就可以就找到结果,无需选择分类的栏目。

对这样的要求第一个想到的就是Apache Lucene,加上一个开源的中文分词包,整一套分词表 很好解决这个需求,但如果把这个需求深入的去考虑,特别是网站随着业务的发展越做越大的时候,用户数据和请求量上来的时候,事情并非那么简单了,以下是我们想到的几个主要的问题和瓶颈:

1.如果搜索的服务器和网站提供内容的服务器放在一台机器上压力将会很大,为了不在性能上相互影响,需要进行分离,

2.搜索的压力如果集中在一台机器上,无法解决瞬间的压力,也不便于将来的扩展,需要对搜索的计算进行压力分载,

3.失效转发是必然的,无需解释,需要解决,

4.系统数据量的增长导致索引文件也不断的增大,如果保存在一个索引文件中,操作和维护起来很麻烦,

5.做到索引库和数据库的内容实时更新,并且对全文索引的读/写进行分离。

系统描述:

1.用户的请求通过负载均衡设备进行分发到App Server的集群上,负载均衡设备分载大量的用户搜索请求,App Server是一组Web容器,例如GlassFish、Tomcat、Jetty.

2.每个Web容器中部署相同的应用程序,App Server的应用程序中包含Lucene的RMI 客户端和一个监听请求 删除、添加、更新的监听器。

3.App Server中Lucene的客户端通过RMI协议对分布式的Lucene Server端进行远程调用,得到查询结果后返回给App Server的Lucene的RMI 客户端,Search Server不仅是一个集群环境,还可以针对业务要求对Search Server进行分组。

4.网络存储设备上部署了切分过索引文件,这样Lucene RMI Server端加载/读取载网络存储设备上的索引文件效率将会比没有切分以前效率要高,并且可以提高容错能力。

5.当用户更新数据时,可以调用 App Server的 Action Listener服务,根据lucene的规则可以对索引文件同时读,不可以同时写入的原则,所以将所有的更新操作请求放入一个队列中,队列可以用JMS实现,也可以用java/util的Queue 来实现。这样依次向索引文件进行操作。





查看大图请点这里

三、代码实现

和客户有保密协议,在此不方便透露代码,只将最初的demo/test示例和demo代码运行的方法写在blog上。

示例中一共4个Java程序,分别是:

·IndexTools.java(工具类),

·SearchServerA.java/SearchServerB.java (2个服务器端程序),

· SearchClient.java (请求的客户端程序)

运行方法

copy到eclipse中,客户端和服务器启动都通过mian方法,所以可以在eclipse中直接运行。运行此demo需要2个jar包,分别是lucene-core-2.9.3.jar 和contrib\remote目录下的 lucene-remote-2.9.3.jar。

先运行 SearchServerA 和SearchServerB 2个服务器端程序 将会自动在你的 c 盘下创建一个index文件夹,里面包含 a、b 这2个目录,目录中就是索引文件。

服务端代码示例,

private static final String indexdir = "c:/index/a"; // 索引文件存放的位置,这儿写的是本地磁盘

private static final int ServerPort = 1099; // 服务器端创建的端口号

private static final String context ="What's you name , My name is JavaBloger search serverA."; // 向索引文件中添加的正文内容

@SuppressWarnings("deprecation")

public static void main(String[] args) throws Exception {

IndexTools.createIndex(new File(indexdir),context); // 传入工具类里面的2个参数

Searchable[] searchables = new Searchable[1]; // 创建Searchable实例,根据索引文件可以是多个,这里只写了一个

searchables[0] =new IndexSearcher(indexdir);

LocateRegistry.createRegistry(ServerPort); // 注册服务器的端口

Searcher parallelSearcher = new MultiSearcher(searchables); // 创建网络搜索,对指定的一个或者多个索引目标进行搜索

RemoteSearchable parallelImpl = new RemoteSearchable(parallelSearcher);

Naming.rebind("//localhost:" + ServerPort + "/DistributedSearch",

parallelImpl); // 创建RMI/JDNI的服务器名称,提供搜索客户的入口。

System.out.println("Server A Started!");

}

运行结果,如图所示:



这个结果表示,一个客户端中通过2个远程的服务器端读取不同的索引,显示的一个搜索结果,并且这个结果是带搜索排序的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: