- 浏览: 622288 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
xianzi_2008:
xianzi_2008 写道楼主请教下,我缓存了一个List& ...
Ehcache -
xianzi_2008:
楼主请教下,我缓存了一个List<Bean>对象, ...
Ehcache -
jsdsh:
收藏好.五个字
hibernate之one-to-many详细 -
Tlife:
好!!!!
hibernate------HQL总结 -
yanqingluo:
例子很恰当。
观察者模式
1.多线程索引,共享同一个IndexWriter对象
这种方式效率很慢,主要原因是因为:
- public void addDocument(Document doc, Analyzer analyzer) throws IOException {
- SegmentInfo newSegmentInfo = buildSingleDocSegment(doc, analyzer);
- synchronized (this) {
- ramSegmentInfos.addElement(newSegmentInfo);//这句很占用效率
- maybeFlushRamSegments();
- }
- }
2 多线程索引, 先写到RAMDirectory,再一次性写到FSDirectory
功能:首先向RAMDirectory里写,当达到1000个Document後,再向FSDirectory里写。
当多线程执行时,会大量报java.lang.NullPointerException
自己写的多线程索引的类为(IndexWriterServer,该对象只在Server启动时初始化一次):
- public class IndexWriterServer{
- private static IndexWriter indexWriter = null;
- //private String indexDir ;//索引目录;
- private static CJKAnalyzer analyzer = null;
- private static RAMDirectory ramDir = new RAMDirectory();
- private static IndexWriter ramWriter = null;
- private static int diskFactor = 0;//内存中现在有多少Document
- private static long ramToDistTime = 0;//内存向硬盘写需要多少时间
- private int initValue = 1000;//内存中达到多少Document,才向硬盘写
- private static IndexItem []indexItems = null;
- public IndexWriterServer(String indexDir){
- initIndexWriter(indexDir);
- }
- public void initIndexWriter(String indexDir){
- boolean create = false;//是否创建新的
- analyzer = new CJKAnalyzer();
- Directory directory = this.getDirectory(indexDir);
- //判断是否为索引目录
- if(!IndexReader.indexExists(indexDir)){
- create = true;
- }
- indexWriter = getIndexWriter(directory,create);
- try{
- ramWriter = new IndexWriter(ramDir, analyzer, true);
- }catch(Exception e){
- logger.info(e);
- }
- indexItems = new IndexItem[initValue+2];
- }
- /**
- * 生成单个Item索引
- */
- public boolean generatorItemIndex(IndexItem item, Current __current) throws DatabaseError, RuntimeError{
- boolean isSuccess = true;//是否索引成功
- try{
- Document doc = getItemDocument(item);
- ramWriter.addDocument(doc);//关键代码,错误就是从这里报出来的
- indexItems[diskFactor] = item;//为数据挖掘使用
- diskFactor ++;
- if((diskFactor % initValue) == 0){
- ramToDisk(ramDir,ramWriter,indexWriter);
- //ramWriter = new IndexWriter(ramDir, analyzer, true);
- diskFactor = 0;
- //数据挖掘
- isSuccess = MiningData();
- }
- doc = null;
- logger.info("generator index item link:" + item.itemLink +" success");
- }catch(Exception e){
- logger.info(e);
- e.printStackTrace();
- logger.info("generator index item link:" + item.itemLink +" faiture");
- isSuccess = false;
- }finally{
- item = null;
- }
- return isSuccess;
- }
- public void ramToDisk(RAMDirectory ramDir, IndexWriter ramWriter,IndexWriter writer){
- try{
- ramWriter.close();//关键代码,把fileMap赋值为null了
- ramWriter = new IndexWriter(ramDir, analyzer, true);//重新构建一个ramWriter对象。因为它的fileMap为null了,但是好像并没有太大作用
- Directory ramDirArray[] = new Directory[1];
- ramDirArray[0] = ramDir;
- mergeDirs(writer, ramDirArray);
- }catch(Exception e){
- logger.info(e);
- }
- }
- /**
- * 将内存里的索引信息写到硬盘里
- * @param writer
- * @param ramDirArray
- */
- public void mergeDirs(IndexWriter writer,Directory[] ramDirArray){
- try {
- writer.addIndexes(ramDirArray);
- //optimize();
- } catch (IOException e) {
- logger.info(e);
- }
- }
- }
主要原因大概是因为:在调用ramWriter.close();时,Lucene2.1里RAMDirectory 的close()方法
- public final void close() {
- fileMap = null;
- }
把fileMap 给置null了,当多线程执行ramWriter.addDocument(doc);时,最终执行RAMDirectory 的方法:
- public IndexOutput createOutput(String name) {
- RAMFile file = new RAMFile(this);
- synchronized (this) {
- RAMFile existing = (RAMFile)fileMap.get(name);//fileMap为null,所以报:NullPointerException,
- if (existing!=null) {
- sizeInBytes -= existing.sizeInBytes;
- existing.directory = null;
- }
- fileMap.put(name, file);
- }
- return new RAMOutputStream(file);
- }
提示:在网上搜索了一下,好像这个是lucene的一个bug(http://www.opensubscriber.com/message/java-user@lucene.apache.org/6227647.html),但是好像并没有给出解决方案。
3.多线程索引,每个线程一个IndexWriter对象,每个IndexWriter 绑定一个FSDirectory对象。每个FSDirectory绑定一个本地的磁盘目录(唯一的)。单独开辟一个线程出来监控这些索引线程(监控线程),也就是说负责索引的线程索引完了以后,给这个监控线程的queue里发送一个对象:queue.add(directory);,这个监控现成的queue对象是个全局的。当这个queue的size() > 20 时,监控线程 把这20个索引目录合并(merge):indexWriter.addIndexes(dirs);//合并索引,合并到真正的索引目录里。,合并完了以后,然后删除掉这些已经合并了的目录。
但是这样也有几个bug:
a. 合并线程的速度 小于 索引线程的速度。导致 目录越来越多
b.经常会报一个类似这样的错误:
2007-06-08 10:49:18 INFO [Thread-2] (IndexWriter.java:1070) - java.io.FileNotFoundException: /home/spider/luceneserver/merge/item_d28686afe01f365c5669e1f19a2492c8/_1.cfs (No such file or directory)
4.单线程索引,调几个参数後,效率也非常快(索引一条信息大概在6-30 ms之间)。感觉一般的需求单线程就够用了。这些参数如下:
private int mergeFactor = 100;//磁盘里达到多少後会自动合并
private int maxMergeDocs = 1000;//内存中达到多少会向磁盘写入
private int minMergeDocs = 1000;//lucene2.0已经取消了
private int maxFieldLength = 2000;//索引的最大文章长度
private int maxBufferedDocs = 10000;//这个参数不能要,要不然不会自动合并了
得出的结论是:Lucene的多线程索引会有些问题,如果没有特殊需求,单线程的效率几乎就能满足需求.
如果单线程的速度满足不了你的需求,你可以多开几个应用。每个应用都绑定一个FSDirectory,然后通过search时通过RMI去这些索引目录进行搜索。
RMI Server端,关键性代码:
- private void initRMI(){
- //第一安全配置
- if (System.getSecurityManager() == null) {
- System.setSecurityManager( new RMISecurityManager() );
- }
- //注册
- startRMIRegistry(serverUrl);
- SearcherWork searcherWork = new SearcherWork("//" + serverUrl + "/" + bindName, directory);
- searcherWork.run();
- }
- public class SearcherWork {
- // Logger
- private static Logger logger = Logger.getLogger(SearcherWork.class);
- private String serverUrl =null;
- private Directory directory =null;
- public SearcherWork(){
- }
- public SearcherWork(String serverUrl, Directory directory){
- this.serverUrl = serverUrl;
- this.directory = directory;
- }
- public void run(){
- try{
- Searchable searcher = new IndexSearcher(directory);
- SearchService service = new SearchService(searcher);
- Naming.rebind(serverUrl, service);
- logger.info("RMI Server bind " + serverUrl + " success");
- }catch(Exception e){
- logger.info(e);
- System.out.println(e);
- }
- }
- }
- public class SearchService extends RemoteSearchable implements Searchable {
- public SearchService (Searchable local) throws RemoteException {
- super(local);
- }
- }
客户端关键性代码:
- RemoteLuceneConnector rlc= new RemoteLuceneConnector();
- RemoteSearchable[] rs= rlc.getRemoteSearchers();
- MultiSearcher multi = new MultiSearcher(rs);
- Hits hits = multi.search(new TermQuery(new Term("content","中国")));
评论
private int maxMergeDocs = 1000;//内存中达到多少会向磁盘写入
Determines the largest number of documents ever merged by addDocument().
private int minMergeDocs = 1000;//lucene2.0已经取消了
private int maxBufferedDocs = 10000;//这个参数不能要,要不然不会自动合并了
minMergeDocs没有取消,就是改成setMaxBufferedDocs了。
ramWriter = new IndexWriter(ramDir, analyzer, true);//重新构建一个ramWriter对象。因为它的fileMap为null了,但是好像并没有太大作用
lz你的代码有问题,这个是参数……
在实际中,我会用多线程开多个IndexWriter分别索引到不同的目录,IndexWriter被设计成线程安全的,有同步机制,多线程使用同一个IndexWriter,应该没有多大提高,和lz说的3比较类似,但通常不会合并(索引目录是按数据库表分的)。索引的速度和I/O关系比较大,要么是写入磁盘比较慢,要么是从数据源读取慢,通过调整maxBufferedDocs,写入索引文件这一端应该不会成为瓶颈。但调整到10000很可能服务器没那么大的内存。一般都是1000左右
LUCENE到底是好?还是不好?
还是在普及LUCENE知识???
发表评论
-
通过updateDocument更新索引
2008-09-20 15:57 4867package com.lucene; import ... -
通过addIndexes将内存中的索引加入到磁盘索引
2008-09-20 15:33 2002package com.lucene; import ... -
lucene高亮demo
2007-07-31 17:19 5165java 代码 package com.feed ... -
提取关键词及相应的频率,Field.Store.NO的数据获取
2007-07-11 11:53 30241.提取关键词及相应的频率 java 代码 R ... -
数据挖掘关于分类方面
2007-07-05 14:36 18331.提供自动学习数据,对这些数据进行索引 2。从索引里提取一个 ... -
提取关键词,并排序
2007-06-29 11:10 2512java 代码 //提取内容关键字! 对关键字 ... -
lucene索引参数优化
2007-06-28 15:52 18971。maxBufferedDocs 缓存在内存中的 ... -
lucene支持内存索引
2007-06-28 11:24 3076lucene支持内存索引:这 ... -
关于lucene2.0的创建、检索和删除功能的完整实现
2007-06-28 11:07 1471转载: http://blog.csdn.net/xia ... -
lucene2.0
2007-05-21 14:27 1138Field.Text(java.lang.String, ja ...
相关推荐
**Lucene 应用程序扩展在 ASP.NET 中的实践与应用** Lucene 是一个高性能、全文本搜索库,由 Apache 软件基金会开发。它提供了强大的搜索功能,被广泛应用于各种应用程序,包括网站、数据库和文档管理。在 ASP.NET ...
**Lucene在Web项目中的应用** Lucene是一个高性能、全文本搜索库,由Apache软件基金会开发,它提供了完整的搜索解决方案,包括索引构建、搜索功能以及分词处理。在Java Web项目中,Lucene能够帮助开发者实现高效、...
在探讨“Lucene应用中Pdf文档文本数据提取方法研究”的主题下,我们深入研究了如何在基于Lucene的全文检索系统中高效处理和提取Pdf文档中的文本数据。Lucene作为一款开源的全文检索引擎,虽然提供了强大的全文检索...
**Lucene 3.4 基本应用详解** Lucene 是一个开源的全文搜索引擎库,由Apache软件基金会开发并维护。它提供了高效、可扩展的搜索功能,被广泛应用于各种信息检索系统。本篇文章将深入探讨Lucene 3.4版本的基础应用,...
《Lucene高级应用详解》 在信息技术领域,搜索引擎技术是数据检索的重要手段,而Apache Lucene作为开源全文搜索引擎库,以其高效、灵活的特点被广泛应用于各类项目中。本篇文章将深入探讨Lucene的高级应用,结合...
### Java全文检索引擎Lucene的应用 #### 一、引言 随着信息技术的飞速发展,尤其是数据库技术和数据库管理系统(DBMS)的广泛应用,全球范围内的数据量急剧增长。特别是在科学研究领域,面对海量的数据,传统的手工...
"用 Lucene 加速 Web 搜索应用程序的开发" 这个标题指出,我们将探讨如何利用 Apache Lucene 这个全文搜索引擎库来提升 Web 应用程序的搜索性能。Lucene 是一个开源的Java库,专门用于文本搜索,它提供了高效的索引...
文章主要研究和应用了基于Lucene的搜索引擎,其特点是利用开源网络爬虫工具抓取互联网信息,并通过Lucene的API对特定信息进行索引和搜索。下面详细介绍相关知识点。 1. Lucene基础 Lucene是由Apache软件基金会提供...
《Lucene实战 第2版 》基于Apache的Lucene 3 0 从Lucene核心 Lucene应用 案例分析3个方面详细系统地介绍了Lucene 包括认识Lucene 建立索引 为应用程序添加搜索功能 高级搜索技术 扩展搜索 使用Tika提取文本 Lucene...
Lucene应用是指使用Lucene搜索引擎库构建搜索应用程序的过程。Lucene应用程序可以用于各种领域,包括文本搜索、图片搜索和视频搜索等。 在上面的代码中,我们使用了Lucene搜索引擎库构建了一个文本搜索应用程序。该...
《Lucene4.7在Web应用中的实践:结合SpringMVC与MyBatis3》 在信息化时代,搜索引擎已经成为我们日常获取信息的重要工具。Apache Lucene作为一款强大的全文搜索引擎库,为开发者提供了丰富的功能,帮助构建高效、可...
"Linux 下配置和应用 Lucene" 在本文中,我们将详细介绍如何在 Red Hat Linux 9 下配置和应用 Lucene 2.9.1。这篇文章将对 Lucene 的安装、配置和应用进行详细的讲解,旨在为读者提供一个清晰、详细的指南。 环境...
Lucene是一款高性能、全功能的文本搜索引擎库,它被广泛应用于各种需要进行高效全文检索的应用场景中,例如网站搜索、文档管理等。由于其高度可定制化的特点,开发者可以根据具体需求对Lucene进行配置和优化。 ####...
本案例"lucene的实际应用案例"主要关注如何利用Lucene来创建和管理索引,以便在大量文本数据中进行高效搜索。 在Lucene中,索引是搜索的核心。索引过程主要包括以下几个步骤: 1. **创建索引**: 首先,你需要读取...
**Lucene API 最基本应用** Lucene 是一个高性能、全文本搜索库,由 Apache 软件基金会开发。它提供了一个简单的 Java API,使得开发者能够方便地在应用程序中实现索引和搜索功能。在这个主题中,我们将深入探讨 ...
lucene,lucene教程,lucene讲解。 为了对文档进行索引,Lucene 提供了五个基础的类 public class IndexWriter org.apache.lucene.index.IndexWriter public abstract class Directory org.apache.lucene.store....
《Lucene Web项目应用实例详解》 在信息技术领域,搜索引擎技术是不可或缺的一部分,Apache Lucene作为一款开源全文搜索引擎库,为开发者提供了强大的文本检索能力。本文将深入探讨一个名为“lucene_web”的项目,...
### 基于Lucene的全文检索引擎研究与应用 #### 概述 随着信息技术的飞速发展,尤其是互联网的普及,企业和个人积累了大量的电子文档。如何高效地管理和检索这些文档成为了亟待解决的问题。全文检索技术作为一种...
lucene3.0 lucene3.0 lucene3.0 lucene3.0 lucene3.0