﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-裤衩的天空-文章分类-Lucene研究</title><link>http://www.blogjava.net/ikucha/category/28454.html</link><description /><language>zh-cn</language><lastBuildDate>Sun, 30 Dec 2007 11:01:08 GMT</lastBuildDate><pubDate>Sun, 30 Dec 2007 11:01:08 GMT</pubDate><ttl>60</ttl><item><title>Lucene并发连接实现  问题</title><link>http://www.blogjava.net/ikucha/articles/171238.html</link><dc:creator>付涛</dc:creator><author>付涛</author><pubDate>Fri, 28 Dec 2007 08:23:00 GMT</pubDate><guid>http://www.blogjava.net/ikucha/articles/171238.html</guid><wfw:comment>http://www.blogjava.net/ikucha/comments/171238.html</wfw:comment><comments>http://www.blogjava.net/ikucha/articles/171238.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ikucha/comments/commentRss/171238.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ikucha/services/trackbacks/171238.html</trackback:ping><description><![CDATA[<font color="navy"><strong>import</strong></font> edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;<br />
<font color="navy"><strong>import</strong></font> edu.emory.mathcs.backport.java.util.concurrent.locks.Lock;<br />
<font color="navy"><strong>import</strong></font> edu.emory.mathcs.backport.java.util.concurrent.locks.ReentrantLock;<br />
<font color="navy"><strong>import</strong></font> java.io.File;<br />
<font color="navy"><strong>import</strong></font> java.io.IOException;<br />
<font color="navy"><strong>import</strong></font> org.apache.log4j.Logger;<br />
<font color="navy"><strong>import</strong></font> org.apache.lucene.analysis.Analyzer;<br />
<font color="navy"><strong>import</strong></font> org.apache.lucene.index.IndexReader;<br />
<font color="navy"><strong>import</strong></font> org.apache.lucene.index.IndexWriter;<br />
<font color="navy"><strong>import</strong></font> org.apache.lucene.search.DelayCloseIndexSearcher;<br />
<font color="navy"><strong>import</strong></font> org.apache.lucene.search.IndexSearcher;<br />
<font color="navy"><strong>import</strong></font> org.apache.lucene.store.*;<br />
&nbsp;<br />
<font color="navy"><strong>public</strong></font> <font color="navy"><strong>class</strong></font> ConcurrentLuceneConnection<br />
<font color="navy"><strong>implements</strong></font> ILuceneConnection<br />
<font color="navy">{</font><br />
&nbsp;<br />
<font color="navy"><strong>private</strong></font> <font color="navy"><strong>static</strong></font> Logger log;<br />
<font color="navy"><strong>private</strong></font> <font color="navy"><strong>transient</strong></font> Directory directory;<br />
<font color="navy"><strong>private</strong></font> <font color="navy"><strong>final</strong></font> Analyzer analyzerForIndexing;<br />
<font color="navy"><strong>private</strong></font> <font color="navy"><strong>final</strong></font> ILuceneConnection.Configuration configuration;<br />
<font color="navy"><strong>private</strong></font> <font color="navy"><strong>final</strong></font> Lock indexWriteLock;<br />
<font color="navy"><strong>private</strong></font> <font color="navy"><strong>final</strong></font> Lock searcherCreationLock;<br />
<font color="navy"><strong>private</strong></font> <font color="navy"><strong>final</strong></font> AtomicBoolean batchMode;<br />
<font color="navy"><strong>private</strong></font> DelayCloseIndexSearcher currentSearcher;<br />
&nbsp;<br />
<font color="navy"><strong>public</strong></font> ConcurrentLuceneConnection(Directory directory, Analyzer analyzer, ILuceneConnection.Configuration configuration)<br />
<font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; indexWriteLock = <font color="navy"><strong>new</strong></font> ReentrantLock();<br />
&nbsp;&nbsp;&nbsp;&nbsp; searcherCreationLock = <font color="navy"><strong>new</strong></font> ReentrantLock();<br />
&nbsp;&nbsp;&nbsp;&nbsp; batchMode = <font color="navy"><strong>new</strong></font> AtomicBoolean(<font color="navy"><strong>false</strong></font>);<br />
&nbsp;&nbsp;&nbsp;&nbsp; this.directory = directory;<br />
&nbsp;&nbsp;&nbsp;&nbsp; analyzerForIndexing = analyzer;<br />
&nbsp;&nbsp;&nbsp;&nbsp; this.configuration = configuration;<br />
<font color="navy">}</font><br />
&nbsp;<br />
<font color="navy"><strong>public</strong></font> ConcurrentLuceneConnection(File path, Analyzer analyzer, ILuceneConnection.Configuration configuration)<br />
<font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>this</strong></font>(getDirectory(path), analyzer, configuration);<br />
<font color="navy">}</font><br />
&nbsp;<br />
<font color="navy"><strong>public</strong></font> <font color="navy"><strong>int</strong></font> getNumDocs()<br />
<font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>return</strong></font> ((Integer)withReader(<font color="navy"><strong>new</strong></font> ILuceneConnection.ReaderAction() <font color="navy">{</font><br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>public</strong></font> Object perform(IndexReader reader)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>return</strong></font> <font color="navy"><strong>new</strong></font> Integer(reader.numDocs());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">}</font><br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">}</font>)).intValue();<br />
<font color="navy">}</font><br />
&nbsp;<br />
<font color="navy"><strong>public</strong></font> <font color="navy"><strong>boolean</strong></font> isIndexCreated()<br />
<font color="navy">{</font><br />
<font color="navy"><strong>try</strong></font><font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>return</strong></font> IndexReader.indexExists(directory);<br />
<font color="navy">}</font><font color="navy"><strong>catch</strong></font>(IOException e)<font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>throw</strong></font> <font color="navy"><strong>new</strong></font> LuceneException(e);<br />
<font color="navy">}</font><br />
<font color="navy">}</font><br />
&nbsp;<br />
<font color="navy"><strong>public</strong></font> IndexSearcher leakSearcher()<br />
<font color="navy">{</font><br />
<font color="navy"><strong>try</strong></font><font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>return</strong></font> getOpenedSearcher();<br />
<font color="navy">}</font><font color="navy"><strong>catch</strong></font>(Throwable e)<font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; flipCurrentSearcher();<br />
&nbsp;&nbsp;&nbsp;&nbsp; throwLuceneException(e);<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>throw</strong></font> <font color="navy"><strong>new</strong></font> IllegalStateException(<font color="red">"Exception should have been thrown."</font>);<br />
<font color="navy">}</font><br />
<font color="navy">}</font><br />
&nbsp;<br />
<font color="navy"><strong>public</strong></font> <font color="navy"><strong>void</strong></font> optimize()<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>throws</strong></font> LuceneException<br />
<font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; withWriter(<font color="navy"><strong>new</strong></font> ILuceneConnection.WriterAction() <font color="navy">{</font><br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>public</strong></font> <font color="navy"><strong>void</strong></font> perform(IndexWriter writer)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>throws</strong></font> IOException<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; writer.optimize();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">}</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">}</font>);<br />
<font color="navy">}</font><br />
&nbsp;<br />
<font color="navy"><strong>public</strong></font> <font color="navy"><strong>void</strong></font> recreateIndexDirectory()<br />
<font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; indexWriteLock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>try</strong></font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; directory.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>if</strong></font>(directory <font color="navy"><strong>instanceof</strong></font> FSDirectory)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; directory = FSDirectory.getDirectory(((FSDirectory)directory).getFile(), <font color="navy"><strong>true</strong></font>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>else</strong></font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>if</strong></font>(directory <font color="navy"><strong>instanceof</strong></font> RAMDirectory)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; directory = <font color="navy"><strong>new</strong></font> RAMDirectory();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (<font color="navy"><strong>new</strong></font> IndexWriter(directory, null, <font color="navy"><strong>true</strong></font>)).close();<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">}</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>catch</strong></font>(IOException e)<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>throw</strong></font> <font color="navy"><strong>new</strong></font> LuceneException(<font color="red">"Cannot create index directory."</font>, e);<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">}</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; flipCurrentSearcher();<br />
&nbsp;&nbsp;&nbsp;&nbsp; indexWriteLock.unlock();<br />
<font color="navy">}</font><br />
&nbsp;<br />
<font color="navy"><strong>public</strong></font> <font color="navy"><strong>void</strong></font> close()<br />
<font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; flipCurrentSearcher();<br />
<font color="navy">}</font><br />
&nbsp;<br />
<font color="navy"><strong>public</strong></font> <font color="navy"><strong>void</strong></font> withSearch(ILuceneConnection.SearcherAction action)<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>throws</strong></font> LuceneException<br />
<font color="navy">{</font><br />
<font color="navy"><strong>try</strong></font><font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; IndexSearcher searcher = getOpenedSearcher();<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>boolean</strong></font> b = action.perform(searcher);<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>if</strong></font>(!b)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>throw</strong></font> <font color="navy"><strong>new</strong></font> UnsupportedOperationException(<font color="red">"Searchers are always closed. The searcherAction should always return true, we do not allow them to control closing of the searchers"</font>);<br />
&nbsp;&nbsp;&nbsp;&nbsp; closeSearcher(searcher);<br />
<font color="navy">}</font><font color="navy"><strong>catch</strong></font>(Throwable e)<font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; flipCurrentSearcher();<br />
&nbsp;&nbsp;&nbsp;&nbsp; throwLuceneException(e);<br />
<font color="navy">}</font><br />
<font color="navy">}</font><br />
&nbsp;<br />
<font color="navy"><strong>public</strong></font> Object withReader(ILuceneConnection.ReaderAction action)<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>throws</strong></font> LuceneException<br />
<font color="navy">{</font><br />
<font color="navy"><strong>try</strong></font><font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; IndexSearcher searcher = getOpenedSearcher();<br />
&nbsp;&nbsp;&nbsp;&nbsp; Object obj = action.perform(searcher.getIndexReader());<br />
&nbsp;&nbsp;&nbsp;&nbsp; closeSearcher(searcher);<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>return</strong></font> obj;<br />
<font color="navy">}</font><font color="navy"><strong>catch</strong></font>(Throwable e)<font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; flipCurrentSearcher();<br />
&nbsp;&nbsp;&nbsp;&nbsp; throwLuceneException(e);<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>return</strong></font> <font color="navy"><strong>null</strong></font>;<br />
<font color="navy">}</font><br />
<font color="navy">}</font><br />
&nbsp;<br />
<font color="navy"><strong>public</strong></font> <font color="navy"><strong>void</strong></font> withReaderAndDeletes(ILuceneConnection.ReaderAction action)<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>throws</strong></font> LuceneException<br />
<font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; IndexReader deleter;<br />
&nbsp;&nbsp;&nbsp;&nbsp; indexWriteLock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp; deleter = <font color="navy"><strong>null</strong></font>;<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>try</strong></font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; deleter = constructIndexDeleter();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; action.perform(deleter);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flipCurrentSearcher();<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">}</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>catch</strong></font>(IOException e)<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>throw</strong></font> <font color="navy"><strong>new</strong></font> LuceneException(e);<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">}</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; closeReader(deleter);<br />
&nbsp;&nbsp;&nbsp;&nbsp; indexWriteLock.unlock();<br />
<font color="navy">}</font><br />
&nbsp;<br />
<font color="navy"><strong>public</strong></font> <font color="navy"><strong>void</strong></font> withWriter(ILuceneConnection.WriterAction action)<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>throws</strong></font> LuceneException<br />
<font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; IndexWriter writer;<br />
&nbsp;&nbsp;&nbsp;&nbsp; indexWriteLock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp; writer = <font color="navy"><strong>null</strong></font>;<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>try</strong></font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; writer = constructIndexWriter();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; action.perform(writer);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flipCurrentSearcher();<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">}</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>catch</strong></font>(IOException e)<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>throw</strong></font> <font color="navy"><strong>new</strong></font> LuceneException(e);<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">}</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; closeWriter(writer);<br />
&nbsp;&nbsp;&nbsp;&nbsp; indexWriteLock.unlock();<br />
<font color="navy">}</font><br />
&nbsp;<br />
<font color="navy"><strong>public</strong></font> <font color="navy"><strong>void</strong></font> withDeleteAndWrites(ILuceneConnection.ReaderAction readerAction, ILuceneConnection.WriterAction writerAction)<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>throws</strong></font> LuceneException<br />
<font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; indexWriteLock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp; withReaderAndDeletes(readerAction);<br />
&nbsp;&nbsp;&nbsp;&nbsp; withWriter(writerAction);<br />
&nbsp;&nbsp;&nbsp;&nbsp; indexWriteLock.unlock();<br />
<font color="navy">}</font><br />
&nbsp;<br />
<font color="navy"><strong>public</strong></font> <font color="navy"><strong>void</strong></font> withBatchUpdate(ILuceneConnection.BatchUpdateAction action)<br />
<font color="navy">{</font><br />
<font color="navy"><strong>try</strong></font><font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; indexWriteLock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp; batchMode.set(<font color="navy"><strong>true</strong></font>);<br />
&nbsp;&nbsp;&nbsp;&nbsp; action.perform();<br />
&nbsp;&nbsp;&nbsp;&nbsp; batchMode.set(<font color="navy"><strong>false</strong></font>);<br />
&nbsp;&nbsp;&nbsp;&nbsp; indexWriteLock.unlock();<br />
<font color="navy">}</font><font color="navy"><strong>catch</strong></font>(Exception e)<font color="navy">{</font><br />
throwLuceneException(e);<br />
<font color="navy">}</font><br />
<font color="navy">}</font><br />
&nbsp;<br />
<font color="navy"><strong>public</strong></font> <font color="navy"><strong>void</strong></font> flipCurrentSearcher()<br />
<font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>if</strong></font>(log.isDebugEnabled())<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; log.debug(<font color="red">"Closing current searcher.."</font>);<br />
&nbsp;&nbsp;&nbsp;&nbsp; searcherCreationLock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>if</strong></font>(currentSearcher != <font color="navy"><strong>null</strong></font>)<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp; <font color="navy"><strong>try</strong></font><font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; currentSearcher.closeWhenDone();<br />
&nbsp;&nbsp;&nbsp;&nbsp; currentSearcher = <font color="navy"><strong>null</strong></font>;<br />
&nbsp;&nbsp;&nbsp; <font color="navy">}</font><font color="navy"><strong>catch</strong></font>(Exception e)<font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp; log.error(e);<br />
&nbsp;&nbsp;&nbsp; currentSearcher = <font color="navy"><strong>null</strong></font>;<br />
&nbsp;&nbsp;&nbsp; <font color="navy">}</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">}</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; searcherCreationLock.unlock();<br />
<font color="navy">}</font><br />
&nbsp;<br />
<font color="navy"><strong>private</strong></font> DelayCloseIndexSearcher getOpenedSearcher()<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>throws</strong></font> IOException<br />
<font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; searcherCreationLock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp; DelayCloseIndexSearcher delaycloseindexsearcher;<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>if</strong></font>(currentSearcher == <font color="navy"><strong>null</strong></font>)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentSearcher = <font color="navy"><strong>new</strong></font> DelayCloseIndexSearcher(directory);<br />
&nbsp;&nbsp;&nbsp;&nbsp; currentSearcher.open();<br />
&nbsp;&nbsp;&nbsp;&nbsp; delaycloseindexsearcher = currentSearcher;<br />
&nbsp;&nbsp;&nbsp;&nbsp; searcherCreationLock.unlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>return</strong></font> delaycloseindexsearcher;<br />
<font color="navy">}</font><br />
&nbsp;<br />
<font color="navy"><strong>private</strong></font> IndexReader constructIndexDeleter()<br />
<font color="navy">{</font><br />
<font color="navy"><strong>try</strong></font><font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>return</strong></font> IndexReader.open(directory);<br />
<font color="navy">}</font><font color="navy"><strong>catch</strong></font>(IOException e)<font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>throw</strong></font> <font color="navy"><strong>new</strong></font> LuceneException(e);<br />
<font color="navy">}</font><br />
<font color="navy">}</font><br />
&nbsp;<br />
<font color="navy"><strong>private</strong></font> <font color="navy"><strong>void</strong></font> closeReader(IndexReader reader)<br />
<font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>try</strong></font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>if</strong></font>(reader != <font color="navy"><strong>null</strong></font>)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>if</strong></font>(log.isDebugEnabled())<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; log.debug(Thread.currentThread().getName() + <font color="red">"## closing reader"</font>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reader.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">}</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">}</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>catch</strong></font>(IOException e)<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; log.error(<font color="red">"Error closing reader. "</font> + e, e);<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">}</font><br />
<font color="navy">}</font><br />
&nbsp;<br />
<font color="navy"><strong>private</strong></font> <font color="navy"><strong>void</strong></font> closeSearcher(IndexSearcher searcher)<br />
<font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>try</strong></font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>if</strong></font>(searcher != <font color="navy"><strong>null</strong></font>)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; searcher.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">}</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>catch</strong></font>(IOException e)<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; log.error(<font color="red">"Error occurred while closing searcher."</font>, e);<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">}</font><br />
<font color="navy">}</font><br />
&nbsp;<br />
<font color="navy"><strong>private</strong></font> <font color="navy"><strong>void</strong></font> closeWriter(IndexWriter writer)<br />
<font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>try</strong></font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>if</strong></font>(writer != <font color="navy"><strong>null</strong></font>)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>if</strong></font>(log.isDebugEnabled())<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; log.debug(<font color="red">"## closing writer"</font>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; writer.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">}</font> <font color="navy"><strong>else</strong></font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; log.warn(<font color="red">"## trying to close null writer."</font>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">}</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">}</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>catch</strong></font>(IOException e)<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; log.error(<font color="red">"Error closing writer. "</font> + e, e);<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">}</font><br />
<font color="navy">}</font><br />
&nbsp;<br />
<font color="navy"><strong>private</strong></font> IndexWriter constructIndexWriter()<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>throws</strong></font> LuceneException<br />
<font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; IndexWriter indexWriter;<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>if</strong></font>(log.isDebugEnabled())<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; log.debug(Thread.currentThread().getName() + <font color="red">"## opening writer"</font>);<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>try</strong></font><font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; indexWriter = <font color="navy"><strong>new</strong></font> IndexWriter(directory, analyzerForIndexing, <font color="navy"><strong>false</strong></font>);<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>if</strong></font>(batchMode.get())<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; indexWriter.setMaxBufferedDocs(configuration.getBatchMaxBufferedDocs());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; indexWriter.setMaxMergeDocs(configuration.getBatchMaxMergeDocs());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; indexWriter.setMergeFactor(configuration.getBatchMergeFactor());<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">}</font> <font color="navy"><strong>else</strong></font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; indexWriter.setMaxBufferedDocs(configuration.getInteractiveMaxBufferedDocs());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; indexWriter.setMaxMergeDocs(configuration.getInteractiveMaxMergeDocs());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; indexWriter.setMergeFactor(configuration.getInteractiveMergeFactor());<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">}</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; indexWriter.setMaxFieldLength(configuration.getMaxFieldLength());<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>return</strong></font> indexWriter;<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">}</font><font color="navy"><strong>catch</strong></font>(IOException e)<font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>throw</strong></font> <font color="navy"><strong>new</strong></font> LuceneException(e);<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy">}</font><br />
<font color="navy">}</font><br />
&nbsp;<br />
<font color="navy"><strong>private</strong></font> <font color="navy"><strong>void</strong></font> throwLuceneException(Throwable e)<br />
<font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>if</strong></font>(e <font color="navy"><strong>instanceof</strong></font> Error)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>throw</strong></font> (Error)e;<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>if</strong></font>(e <font color="navy"><strong>instanceof</strong></font> RuntimeException)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>throw</strong></font> (RuntimeException)e;<br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>else</strong></font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>throw</strong></font> <font color="navy"><strong>new</strong></font> LuceneException(e);<br />
<font color="navy">}</font><br />
&nbsp;<br />
<font color="navy"><strong>private</strong></font> <font color="navy"><strong>static</strong></font> Directory getDirectory(File path)<br />
<font color="navy">{</font><br />
<font color="navy"><strong>try</strong></font><font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>return</strong></font> FSDirectory.getDirectory(path, <font color="navy"><strong>false</strong></font>);<br />
<font color="navy">}</font><font color="navy"><strong>catch</strong></font>(IOException e)<font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; <font color="navy"><strong>throw</strong></font> <font color="navy"><strong>new</strong></font> LuceneException(e);<br />
<font color="navy">}</font><br />
<font color="navy">}</font><br />
&nbsp;<br />
<font color="navy"><strong>static</strong></font> <br />
<font color="navy">{</font><br />
&nbsp;&nbsp;&nbsp;&nbsp; log = Logger.getLogger(ConcurrentLuceneConnection.class);<br />
<font color="navy">}</font><br />
<font color="navy">}<br />
网上找到的只有这个针对lucene分布式介绍，测试还是有问题，在写索引时还是会出现LOCK问题。<br />
</font>
<img src ="http://www.blogjava.net/ikucha/aggbug/171238.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ikucha/" target="_blank">付涛</a> 2007-12-28 16:23 <a href="http://www.blogjava.net/ikucha/articles/171238.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Lucene和Nutch的存储机制和机构分析</title><link>http://www.blogjava.net/ikucha/articles/171230.html</link><dc:creator>付涛</dc:creator><author>付涛</author><pubDate>Fri, 28 Dec 2007 07:55:00 GMT</pubDate><guid>http://www.blogjava.net/ikucha/articles/171230.html</guid><wfw:comment>http://www.blogjava.net/ikucha/comments/171230.html</wfw:comment><comments>http://www.blogjava.net/ikucha/articles/171230.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ikucha/comments/commentRss/171230.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ikucha/services/trackbacks/171230.html</trackback:ping><description><![CDATA[<p>主题：解决nutch的segmens的拆分与nutch crawl的重载(重新构建)问题<br />
主要内容<br />
一、Lucene的索引机制与索引文件结构<br />
二、Nutch的爬虫分析与文件结构分析<br />
三、Nutch segments的拆分索引实现方案<br />
一、Lucene的索引机制与索引文件结构<br />
1、Lucene的索引机制<br />
2、Lucene文件格式<br />
&nbsp;_0.f0，_0.f1 文档文件<br />
&nbsp;_0.fnm域集合信息文件 <br />
&nbsp;0.frq; 0.prx位置与频率文件 <br />
&nbsp;*.fdt和*.fdx构成了域值/域索引文件<br />
&nbsp;segment1.nrm标准化因子 <br />
&nbsp;&nbsp;- segments索引块文件 <br />
&nbsp;- deletable保存已删除文件的记录 <br />
&nbsp;-*.tii和*.tis构成了项字典 <br />
&nbsp;-lock(无扩展名) 用来控制读写的同步 <br />
二、Nutch的爬虫分析<br />
&nbsp;Nutch segments分析<br />
&nbsp;Nutch 的文件结构分析<br />
三、Nutch segments的拆分解决方案</p>
<p>Lucene采取的是倒排索引结构存储结构建立反向索引。对爬取回来的信息通过Lucene Analyzer分词器提取出索引项以相关信息，如索引项的出现频率。然后分词器把这些信息写到索引文件中。其核心在于Lucene的索引文件结构（倒排索引结构），首先理解&#8221;反向索引&#8221;的概念。</p>
<p>反向索引是一种以索引项为中心来组织文档的方式，每个索引项指向一个文档序列，这个序列中的文档都包含该索引项。相反，在正向索引中，文档占据了中心的位置，每个文档指向了一个它所包含的索引项的序列。你可以利用反向索引轻松的找到那些文档包含了特定的索引项。 Lucene使用了反向索引作为其基本的索引结构。</p>
<p>Lucene索引index由若干段(segment)组成,每一段由若干的文档(document)组成,每一个文档由若干的域(field)组成,每一个域由若干的项(term)组成。项是最小的索引概念单位,它直接代表了一个字符串以及其在文件中的位置、出现次数等信息。域是一个关联的元组,由一个域名和一个域值组成,域名是一个字串,域值是一个项,比如将&#8220;标题&#8221;和实际标题的项组成的域。</p>
<p>文档是提取了某个文件中的所有信息之后的结果,这些组成了段,或者称为一个子索引。子索引可以组合为索引,也可以合并为一个新的包含了所有合并项内部元素的子索引。</p>
<p>Lucene采用倒排索引结构索引被处理为一个目录(文件夹),其中含有的所有文件即为其内容,这些文件按照所属的段不同分组存放,同组的文件拥有相同的文件名,不同的扩展名。此外还有三个文件,分别用来保存所有的段的记录、保存已删除文件的记录和控制读写的同步,它们分别是segments, deletable和lock文件,都没有扩展名。</p>
<p>每个段包含一组文件,它们的文件扩展名不同,但是文件名均为记录在文件segments中段的名字每个 段的文件中。<br />
主要记录了两大类的信息：域集合与项集合。由于索引信息是静态存储的,域集合与项集合中的文件组采用了一种类似的存储办法：一个小型的索引文件,运行时载 入内存；一个对应于索引文件的实际信息文件,可以按照索引中指示的偏移量随机访问；索引文件与信息文件在记录的排列顺序上存在隐式的对应关系,即索引文件中按照&#8220;索引项</p>
<p>1、索引项2&#8230;&#8221;排列,则信息文件则也按照&#8220;信息项1、信息项2&#8230;&#8221;排列。域集合与项集合之间则通过域的在域记录文件(比如segment1.fnm)中所记录的域记录号维持对应关系,segment1.fdx与segment1.tii中就是通过这种方式保持联系。这样,域集合和项集合不仅仅联系起来,而且其中的文件之间也相互联系起来。这样,整个段的索引信息</p>
<p>就通过这些文档有机的组成。<br />
Lucene所采用的索引文件格式。基本上而言,它是一个倒排索引。,但是Lucene在文件的安排上做了一些努力,比如使用索引/信息文件的方式,从文件安排的形式上提高查找的效率。 </p>
<p>(_0.f0，_0.f1 文档文件)<br />
文档号（Document Number）<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 编号方式：Lucene用一个整形（interger）的文档号来指示文档。第一个被加入到索引的文档就是0号，顺序加入的文档将得到一个由前一个号码递增而来的号码。 <br />
&nbsp;&nbsp;&nbsp;&nbsp; 标准的技术是根据每一段号码多少为每一段分配一个段号。将段内文档号转换到段外时，加上段号。将某段外的文档号转换到段内时，根据每段中可能的转换后号码范围来判断文档属于那一段，并减调这一段的段号。例如有两个含5个文档的段合并，那么第一段的段号就是0，第二段段号5。第二段中的第三个文档，在段外的号码就是8。 <br />
(_0.fnm域集合信息)<br />
&nbsp;&nbsp;&nbsp; 索引中的文档由一个或者多个域组成，这个文件包含了每个索引块中的域的信息。<br />
&nbsp;&nbsp;所有域名都存储在这个文件的域集合信息中文件中的域根据它们的次序编号。因此域0是文件中的第一个域，域1是接下来的 ，这个和文档号的编号方式相同。 </p>
<p>项频数 .frq文件包含每一项的文档的列表，还有该项在对应文档中出现的频数。 <br />
项位置 .prx文件包含了某文档中某项出现的位置信息的列表。 </p>
<p>(0.frq; 0.prx位置与频率文件)<br />
项频数 .frq文件包含每一项的文档的列表，还有该项在对应文档中出现的频数。 <br />
项位置 .prx文件包含了某文档中某项出现的位置信息的列表。 </p>
<p>(*.fdt和*.fdx构成了域值/域索引文件)<br />
域值存储表（Stored Fields）域值存储表使用域索引 .fdx与域值 .fdt两个文件表示。</p>
<p>(segment1.nrm标准化因子)<br />
.nrm文件包含了每个文档的标准化因子，其主要用在评分排序机制中。</p>
<p>(segments索引块文件)<br />
Segments索引块又称segment段，这个文件包含了索引中的索引块信息，这个文件包含了每个索引块的名字以及大小等信息。 </p>
<p>(deletable保存已删除文件的记录)<br />
deletetable的文件包含了索引不再使用的文件的名字，这些文件可能并没有被实际的删除。<br />
&nbsp;.del文件是可选的，只有在某段中存在删除操作后才存在。</p>
<p>(*.tii和*.tis构成了项字典 )<br />
项字典用项信息（.tis文件）和项信息索引（.tii文件） 两个文件表示。<br />
项信息索引（.tii文件）<br />
每个项信息索引文件包含.tis文件中的128个条目，依照条目在.tis文件中的顺序。这样设计是为了一次将索引信息读入内存能，然后使用它来随机的访问.tis文件。这个文件的结构和.tis文件非常类似，只在每个条目记录上增加了一个变量IndexDelta。 </p>
<p>(lock(无扩展名) 用来控制读写的同步)<br />
主要是用于防止进程在使用索引时，被其它文件操作修改索引。</p>
<p>Nutch的爬虫分析</p>
<p>1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 创建一个新的WebDb (admin db -create)；<br />
2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 将抓取起始URLs写入WebDB中 (inject)； <br />
3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 根据WebDB生成fetchlist并写入相应的segment(generate)； <br />
4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 根据fetchlist中的URL抓取网页 (fetch).；<br />
5.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 根据抓取网页更新WebDb (updatedb).<br />
通过3—5这个循环就可以实现Nutch的深度抓取。</p>
<p>Nutch segments分析<br />
对于segments/segment/下的文件以后分析）结构，在nutch爬虫运行后在webdb文件夹下一共产生如下五个文件： <br />
linksByMD5 linksByURL pagesByMD5 pagesByURL stats<br />
其中：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Stats文件用来存放爬虫爬行后的版本信息，处理网页数量，连接数量；<br />
pagesByURL等其余四个文件夹下均有两个文件――index和data，其中data文件用来存放有序的key／value对，排序是通过选择不同的key和comparator来改变的，当然里面会有一些其他信息， 比如在pagesByURL中，就每隔一定长度的key／value对放入一个用来定位的信息（syn）；index文件用来存放索引，但是这个索引文件也是一个有序的，这个里面存放的是key和位置信息，但是在data文件中出现的key在这个index中都能找到的，它为了节省空间，实施了每隔一段key／value建立一条索引，这样在查找的时候，因为是有序的，所以采用２分查找，如果找不到，则返回最后时候的最小的位置信息，这个位置离我们要找的目标是相当近的，然后在data文件的这个位置向前找就可以很快找到了！<br />
另外，nutch维持这个webdb的方式是，在填加，删除网页或者连接时，并不是直接向这个webdb中填加网页或者连接，而是在WebDBWriter 中的内部类PageInstructionWriter或者LinkInstructionWriter中填加一条对网页操作的命令，然后最后对存放的命令进行排序去重，最后将这个命令与现有的webdb中存放的网页数据进行合并；</p>
<p>Fetcher类是进行实际网页抓取时候运行的类，爬虫产生的文件或文件夹都是由这个类产生的， Nutch提供了选项―是否对抓回的网页进行parse（解析），如果这个选项设置为false，将没有parseddata和parsedtext这两个文件夹。<br />
nutch爬虫产生的文件几乎都是key/value对，不同的只是key/value的种类和值不同，爬虫运行后在segments文件夹的子文件夹产生<br />
如下几个文件夹： content fetcher fetchlist index parse_data parse_text</p>
<p>其中content文件夹存放的内容对应protocol包中的content类；fetcher文件夹存放的内容对应的是fetcher包中的FetcherOutput类；fetchlist对应pagedb包总的fetchlist类；parse_data和parse_text分别对应parse包中的ParseData和ParseText类； </p>
<p>(Nutch segments)<br />
如上面Nutch segments分析所述，对Nutch的segments有了清楚的了解。<br />
提示点：Lucene 中的segment和Nutch中的不同，Lucene中的segment是索引index的一部分，但是Nutch中的segment只是WebDB中 各个部分网页的内容和索引，最后通过其生成的index跟这些segment已经毫无关系了。<br />
&nbsp;<br />
(Nutch crawldb)<br />
其主要是segments段的crawl_fetch与parse_data的数据。并利用其crawldb循环fetch 生成segments深度抓取。</p>
<p>(Nutch linkdb)<br />
其存放的为segments所有段的crawl_fetch数据，其URL列表。</p>
<p>(Nutch indexes)<br />
由Nutch crawldb,linkdb segments生成indexes索引集。其存放结构是结合Lucene的索引机制存放的。</p>
<p>(Nutch index)<br />
由nutch indexes 单独提取索引信息。其索引结果可利用Luke进行索引结果查询。</p>
<p>Nutch 在tomcat下使用的资源主要是segments,linkdb,indexes。</p>
<p>nutch segments的拆分解决方案<br />
从上面的分析可以得出Nutch的爬虫数据都以segments段存放信息。<br />
我们只需要对segments进行slice拆分，就可以重新构造crawl数据源结构。<br />
然后再利用nutch的相应操作完成对nutch segments的拆分与重构。&nbsp;</p><img src ="http://www.blogjava.net/ikucha/aggbug/171230.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ikucha/" target="_blank">付涛</a> 2007-12-28 15:55 <a href="http://www.blogjava.net/ikucha/articles/171230.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>