newweblifelucene的缓存机制分析_第1页
newweblifelucene的缓存机制分析_第2页
newweblifelucene的缓存机制分析_第3页
newweblifelucene的缓存机制分析_第4页
newweblifelucene的缓存机制分析_第5页
免费预览已结束,剩余1页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、new web life lucene 的缓存机制分析lucene 的缓存可分为两类:filter cache 和 field cache。filter cache的实现类为CachingWrapperFilter ,用来缓存其他 Filter 的查询结果。field cache的实现类是FieldCache,缓存用于排 序的 field 的值。简单来说, filter Cache 用于查询缓存, field cache用于排序。这两种缓存的生存周期都是在一个 IndexReader 实例内,因此提高 Lucene 查询性能的关键在于 如何维护和使用同一个lndexReader(即IndexS

2、earcher)。1、Filter Cache 从严格意义上来说, lucene 没有查询类似数据库 服务器的数据高速缓存。lucene的Filter缓存实现类是 CachingWrapperFilter,它缓存了查出来的bits。另夕卜 lucene还提供了 FilterManager ,一个单例对象,用来缓存 Filter 本 身。下面是 CachingWrapperFilter 的具体实现: public class CachingWrapperFilter extends Filter protected Filter filter;protected transient Map ca

3、che;/ 这是作为缓存使用的 mappublic CachingWrapperFilter(Filter filter) this.filter = filter;public BitSet bits(IndexReader reader) throws IOException if (cache = null) cache = newWeakHashMap();/ 采用 WeakHashMap 实现,由 JVM 回收内 存synchronized (cache) / check cacheBitSet cached = (BitSet) cache.get(reader);/key 为 I

4、ndexReader,value 为 BitSet,所以该缓存生存周期在一个 IndexReader 内 if (cached != null) return cached;/ 若没有找到缓存,则重新读取 final BitSet bits = filter.bits(reader);synchronized (cache) / update cachecache.put(reader, bits);return bits; 在 FilterManager 里, 采用 Filter.hashCode() 作为 key 的,所以使用的时候应该在自 定义的Filter类中重载hashCode()方

5、法。例子:Filter filter=FilterManager.getInstance().getFilter(new CachingWrapperFilter(new MyFilter(); 如果该 filter 已经存 在,在 FilterManager 返回该 Filter 的缓存(带有 bit 缓存), 否则返回本身(不带 bit 缓存的)。 FilterManager 里有个定时 线程,会定期清理缓存,以防造成内存溢出错误。2、field缓存field缓存是用来排序用的。lucene会将需要排序的字段 都读到内存来进行排序,所占内存大小和文档数目相关。经 常有人用lucene做排序

6、出现内存溢出的问题,一般是因为每次查询都启动新的searcher实例进行查询,当并发大的时候, 造成多个Searcher实例同时装载排序字段,引起内存溢出。 Field 缓存的实现类是 FieldCacheImpl ,下面我们看看排序时 怎么用到Field缓存的:在IndexSearcher类里的方法,有关 排序的查询都回调用到此方法: public TopFieldDocs search(Weight weight, Filter filter, final int nDocs,Sort sort)throws IOException TopFieldDocCollector collect

7、or =new TopFieldDocCollector(reader, sort, nDocs);/ 排序操作由TopFieldDocCollector 实现 search(weight, filter, collector);/ 开 始查询 ,查询结果回调 Collector.collect() 方法时实现排序 return (TopFieldDocs)collector.topDocs();/ 返回 TopFieldDocs 对象,这个对象和 TopDocs 的差异在于 TopFieldDocs 里包含 排序字段的信息,包括字段名和字段值。其中 TopFieldDocs 中 ScoreD

8、oc 的实例是 FieldDoc 下面看看 TopFieldDocCollector.collect() 是怎么实现的: public void collect(int doc, float score) if (score 0.0f) totalHits+;if (reusableFD = null)reusableFD = new FieldDoc(doc, score);else reusableFD.score = score;reusableFD.doc = doc;reusableFD = (FieldDoc) hq.insertWithOverflow(reusableFD);/

9、hq 是 FieldSortedHitQueue 对象,一个 PriorityQueue 的子类, insertWithOverflow() 实现一个固定大小的排序队列,排序靠 后的对象被挤出队列 FieldSortedHitQueue 是通过重载 lessThan()方法来实现排序功能的:*/protected booleanlessThan (final Object a, final Object b) final ScoreDoc docA = (ScoreDoc) a;final ScoreDoc docB = (ScoreDoc) b;/ run comparatorsfinal

10、int n = comparators.length;int c = 0;for (int i=0; i docB.doc;return c 0;comparators 实在 FieldSortedHitQueue 的构造函数里创建的: public FieldSortedHitQueue (IndexReader reader, SortField fields, int size)throws IOException final int n = fields.length;comparators = new ScoreDocComparatorn;this.fields = new Sor

11、tFieldn;for (int i=0; in; +i) String fieldname = fieldsi.getField();comparatorsi = getCachedComparator (reader, fieldname, fieldsi.getType(), fieldsi.getLocale(), fieldsi.getFactory();/ 调用 getCachedComparator 方法获得缓 存的 comparators,comparator 是 ScoreDocComparator 的实例 if (comparatorsi.sortType() = Sort

12、Field.STRING) this.fieldsi = new SortField (fieldname, fieldsi.getLocale(), fieldsi.getReverse(); else this.fieldsi = new SortField (fieldname, comparatorsi.sortType(), fieldsi.getReverse();initialize (size); 下面看看 getCachedComparator ()的实现: static final FieldCacheImpl.Cache Comparators = new FieldCa

13、cheImpl.Cache() 。 static ScoreDocComparator getCachedComparator (IndexReader reader, String field, int type,Locale locale, SortComparatorSource factory)throws IOException / 以下两种不需要读取字段 if (type = SortField.DOC) return ScoreDocComparator.INDEXORDER;/ 按索引顺序排序 if (type = SortField.SCORE) return ScoreDo

14、cComparator.RELEV ANCE;/ 按相关度排序 FieldCacheImpl.Entry entry = (factory != null) new FieldCacheImpl.Entry (field, factory): new FieldCacheImpl.Entry (field, type, locale);/ 其他类型的排序需 要读取字段到缓存中 return (ScoreDocComparator)Comparators.get(reader, entry);/Comparators 是一个 FieldCache 的实例 呵呵,好多代 码阿,幸好马上就到终点了。

15、Comparators.get()方法根据排序字段类型的不同, 返回 ScoreDocComparator 的不同实现, 下 面我们看看 String 类型的实现,就可以知道什么时候调用 fieldCache 了: static ScoreDocComparator comparatorstring (final IndexReader reader, final String fieldname)throws IOException final String field = ern();/ 下面代码 读取缓存, 得到字段值和文档 id 的对应关系, 如果缓存不存 在

16、,则读取索引文件。缓存的生命周期是和 IndexReader 一 样,所以不同查询使用同一个Searcher,可以保证排序缓存只有一个,不会出现内存溢出的问题 finalFieldCache.StringIndex index =FieldCache.DEFAULT.getStringIndex (reader, field);return new ScoreDocComparator () public final int compare (final ScoreDoc i, final ScoreDoc j) final int fi = index.orderi.doc;/index.order 的值是按自定义字段的排序, 数组的索引是 lucene docid ;可以看看 getStringIndex 的具体 实现来看看这些值是怎么读进来的,这里就不详细说明了 final int fj = index.orde

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论