lucene的分布式搜索-入门篇
我的废话:
前些日子客户对以前网站搜索功能不太满意,因为用户输入关键字进行查询时要再选择对应的分类栏目,用户体验不是很到位。所以找我们对他的网站提供全文检索的功能,跟搜索引擎类似输入一组关键字就可以就找到结果,无需选择分类的栏目。
对这样的要求第一个想到的就是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个远程的服务器端读取不同的索引,显示的一个搜索结果,并且这个结果是带搜索排序的。
上述实例中的源代码下载
相关文章:
LinkedIn的线上搜索 — 分布式搜索相关
–end–

本文由J2ee企业顾问-黄毅创作,并已采用创作共用署名2.5中国大陆版许可证授权。
评论
Comment from ww
Time 2011年07月20日 at 3:48 下午
求代码
Comment from liujf
Time 2011年07月23日 at 10:21 上午
内容就是我要关注的。可惜代码示例代码不能下载。能发代码示例给我吗?529829467@qq.com
Comment from xiaoha
Time 2011年09月13日 at 11:34 上午
代码下载不下来,能把你的这个demo的源代码发我一份吗?万分感谢! 515672779@qq.com
Comment from xiaoha
Time 2011年09月13日 at 11:37 上午
急用,可代码下载不下来,更发我一份这个demo的源代码吗?万分感谢!515672779@qq.com
Comment from bruce
Time 2011年10月28日 at 11:31 上午
楼主麻烦发份源码啊
Comment from 罗昕
Time 2011年11月14日 at 4:26 下午
你好,我正好也在做这个功能,用到分布式检索,两个数据库在2台机器上,输入关键字进行搜索!能发个测试的用列给我吗?谢谢!我的邮箱:568673087@qq.com
Comment from Kenny
Time 2011年11月19日 at 11:41 下午
Hi,Could you give me a copy? Thanks a lot.
Comment from hotwater
Time 2011年11月30日 at 6:49 下午
你好,正为这个发愁呢,给我代码吧 非常感谢啊!ker623@163.com
Comment from Robust
Time 2011年12月16日 at 10:27 下午
楼主求代码,谢谢啊
670797485@qq.com
Comment from bhhzd
Time 2012年01月3日 at 5:41 下午
发我一份 demo/test示例 吧,那个地址下载不了啊 bhhzd@163.com
Comment from likehua
Time 2012年02月20日 at 5:29 下午
楼主,也发份源码给我,谢谢!那个链接下载不了!我的邮箱是:likehua2736@gmail.com






Comment from keren
Time 2010年11月20日 at 11:58 下午
能发份例子的源码给我吗,谢谢!