`
lxwt909
  • 浏览: 572234 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Lucene5学习之Directory理解

阅读更多

Directory即Lucene中对索引目录的一个抽象,体现到API上,它被设计为一个抽象类,类里面定义了一些抽象方法,如listAll列出目录下所有文件,deleteFile(String name) 根据文件名称删除索引文件,这个都是文件的基本操作,其中比较重要的一个接口方法是makeLock,为什么要为索引目录加锁?其实就跟你上厕所为什么要锁门是一样一样滴?我没拉完你就给我乖乖等着。

 BaseDirectory是Directory的一个子类,它默认实现了makeLock方法,

 

@Override
  public final Lock makeLock(String name) {
    return lockFactory.makeLock(this, name);
  }

 这里的lockFactory仍然是一个抽象类,由子类传入传入具体的lockFactory工厂实现来创建不同的Lock实例FSDirectory是针对文件系统的一个Directory实现,即使用这个Directory就可以把索引文件存储到我们的文件系统里了。FSDirectory下面又有3个子类,分别是SimpleFSDirectory,NIOFSDirectory,MMapDirectory,

 

SimpleFSDirectory:它是基于文件系统的索引目录的一个简单实现,它在多线程环境下性能表现很差,不支持并发读写索引文件。

NIOFSDirectory:顾名思义,它就是使用NIO里的FileChannel文件通道来解决并发读写索引文件的,但它在windows平台下有个致命的BUG,官方建议在windows平台下使用RAFDirectory来代替NIOFSDirectory。

MMapDirectory:即基于内存映射的方式把文件load到内存来减少与IO的交互次数,从而提高IO性能,但这部分内存也存在隐患,因为JDK存在一个BUG,就是当IndexInput.close()时并不能有效的交还文件系统里索引文件的文件句柄,这就直接导致索引lock无法释放,一直直到GC回收这部分内存中潜在的对象时该句柄才会释放。由于文件句柄不能有效的立即释放,可能会导致你的硬盘空间得不到立即的释放,所以如果你的应用对于硬盘状况很敏感,这将是一个致命的定时炸蛋(连个zha弹都不让写,ITEye这是怎么了?),放在心里就行,反正暂时这个BUG未解决。(现在硬盘这么廉价,多浪费点硬盘空间也没啥)不过在linux系统上,即使句柄没有释放,当你删除索引文件时会提示是否在delete on last close,当你close时候还是会删除成功的,但索引文件还是会文件系统上占硬盘空间,而在windows平台上你只会得到一个Error,所以又是Windows,你懂的。

上面简单说了下各种FSDirectory的作用,下面简单说下各个Directory中比较重要的一些接口方法:

 

/** Just like {@link #open(Path)}, but allows you to
   *  also specify a custom {@link LockFactory}. */
  public static FSDirectory open(Path path, LockFactory lockFactory) throws IOException {
    if (Constants.JRE_IS_64BIT && MMapDirectory.UNMAP_SUPPORTED) {
      return new MMapDirectory(path, lockFactory);
    } else if (Constants.WINDOWS) {
      return new SimpleFSDirectory(path, lockFactory);
    } else {
      return new NIOFSDirectory(path, lockFactory);
    }
  }

 FSDirectory类里的open方法是使用比较频繁的方法之一,其实内部就是根据用户的操作系统环境和使用的JDK来选择合适的Directory,

 

Constants.JRE_IS_64BIT即表示是否是64位的JDK,

MMapDirectory.UNMAP_SUPPORTED即表示是否支持Direct Buffer,什么叫Direct Buffer?其实Direct Buffer并不是直接分配在堆上的,Direct Buffer不受GC管理,即Direct Buffer是有操作系统来销毁的,但Direct Buffer上对象是由GC负责回收的,Direct Buffer读写之所以快,是因为减少数据拷贝到内核缓冲区的操作,但Direct Buffer是由操作系统负责销毁,所以代价也是很高的。那我们看看Lucene是如何判断是否支持Direct Buffer的?

/**
   * <code>true</code>, if this platform supports unmapping mmapped files.
   */
  public static final boolean UNMAP_SUPPORTED;
  static {
    boolean v;
    try {
      Class.forName("sun.misc.Cleaner");
      Class.forName("java.nio.DirectByteBuffer")
        .getMethod("cleaner");
      v = true;
    } catch (Exception e) {
      v = false;
    }
    UNMAP_SUPPORTED = v;
  }

 其实就是判断JDK里是否有sun.misc.Cleaner这个类,以及java.nio.DirectByteBuffer类是否有cleaner方法。

这两个类都是用于Direct buffer里对象清理工作的。

Oracle/Sun JDK 6中的HotSpot VM只会在年老代GC(full GC/major GC或者concurrent GC都算)的时候才会做reference processing,而在young GC/minor GC时不做。 也就是说,做full GC的话会做reference processing,进而能触发Cleaner对已死的DirectByteBuffer对象做清理工作。而如果很长一段时间里没做过GC或者只做了young GC的话则不会触发Cleaner的工作,那么就可能让本来已经死了的DirectByteBuffer关联的native memory得不到及时释放。 

之所以要保证有上述两个类,就是确保DirectByteBuffer里的内存能得到释放以保证性能,这样你使用MMapDirectory才能体现它的优势又能避免它潜在的隐患。

还有一个比较重要的Directory就是RAMDirectory,就是内存索引目录,即把索引文件数据load到堆中,内部就是用new byte[1024]来缓存索引数据的,这适合于小量的索引文件,RAMDirectory设计之初就不是为百万级别的大数量的索引而设计的,因为它会在你的内存产生数以百万的byte[1024],从而导致频繁GC回收,影响性能,而且它在多线程并发环境下表现也很糟糕,官方建议是:大数据量的索引请使用MMapDirectory,RAMDirectory的使用场景是当你创建索引时可以先把少量的索引放入内存,再switch到FSDirectory flush到file system,利用内存减少与File System访问次数。

另外一个比较重要的Directory就是FileSwitchDirectory,它就是集NIODirectory与MMapDirectory优点与一身的Directory,NIODirectory是直接把文件放入heap buffer中,而MMapDirectory是把文件直接映射到Direct buffer,由于Heap buffer可使用量大而Direct buffer虽然读写速度快,但它受操作系统调度,开辟和销毁的代价太高,不宜过多使用,所以一般我们需要使用NIODirectory来读写比较大的索引文件,而用MMapDirectory来读写相对比较小的文件,两者结合互补你懂的。

同理Lock也有对应的3种实现,就不赘述了。

一般我们使用FSDirectory.open由api自动帮我们来选择合适的Directory即可,特殊情况下可以使用FileSwitchDirectory结合下两种Directory的优点。关于Directory就说这么多了,如果有哪里说的不正确,还望你提出来,谢谢!

 

如果你还有什么问题请加我Q-Q:7-3-6-0-3-1-3-0-5,

或者加裙
一起交流学习!
 

  • 大小: 6 KB
分享到:
评论
3 楼 小礼挥蕉 2015-11-24  
2 楼 majiedota 2015-07-08  
不错哦
1 楼 oaibf 2015-05-27  
感觉很深 看不懂 

相关推荐

    Lucene的的学习资料及案例

    **Lucene学习指南** Lucene是一个高性能、全文检索库,由Apache软件基金会开发并维护,是Java编程语言中广泛使用的搜索引擎库。它提供了一个简单的API,使得开发者能够方便地在应用中实现全文检索功能。本篇文章将...

    Lucene-2.0学习文档

    结合以上文件,我们可以看到Lucene-2.0的学习不仅需要理解基本的索引构建和搜索原理,还需要掌握如何自定义排序规则和分析器以满足特定需求。此外,通过阅读和分析这些源码,开发者还可以深入理解Lucene的内部工作...

    Lucene 3.6 学习笔记

    【Lucene 3.6 学习笔记】 Lucene 是一个高性能、全文本搜索库,广泛应用于各种搜索引擎的开发。本文将深入探讨Lucene 3.6...通过学习这些内容,可以深入理解Lucene的工作机制,并利用其强大的搜索能力构建高效的应用。

    lucene基础学习笔记&源码

    5. **查询解析器(Query Parser)**:用户输入的查询字符串经过查询解析器处理,转化为 Lucene 可理解的查询对象。 6. **搜索器(Searcher)**:搜索器负责执行查询,计算相关性评分,并返回匹配的文档。 7. **...

    lucene 3.5学习笔记

    《Lucene 3.5 学习笔记》 在信息技术高速发展的今天,搜索引擎技术成为了信息检索的核心工具。Apache Lucene,作为一个开源全文...深入学习和理解Lucene的原理和使用,将有助于开发者构建高效、智能的信息检索系统。

    lucene3.5学习笔记

    `IndexWriter` 是 Lucene 中的核心类之一,用于创建或更新索引。它提供了添加文档、删除文档、优化索引等操作的功能。 **1.1.2 Directory** `Directory` 在 Lucene 中代表了存储索引的地方,可以是硬盘上的文件...

    lucene学习总结

    **Lucene学习总结** 在深入理解Lucene之前,我们首先需要了解什么是全文检索。全文检索是一种从大量文本数据中快速查找所需信息的技术。它通过建立索引来实现高效的搜索,而Lucene正是Java环境下最著名的全文搜索...

    本人的Lucene2.9学习笔记

    《深入理解Lucene 2.9.1:构建与搜索的全方位解析》 Lucene,作为一款开源的全文搜索引擎库,被广泛应用于各种信息检索场景。本文将详细讲解Lucene 2.9.1版本的核心概念、架构以及索引创建与搜索的流程。 一、...

    lucene基础学习.pdf

    Apache Lucene 是一个高效的开源信息检索库,用于在应用程序中提供全文搜索功能。...尽管文档的内容由于OCR扫描而存在一定的错误和遗漏,但以上概述提供了一个对Lucene核心概念和功能的较为清晰的理解。

    lucene.net 2.9.1 源码

    3. 查询(Query):用户输入的搜索条件转换为Lucene可以理解的查询对象。QueryParser用于解析用户输入,生成Query对象。 4. 搜索(Search):使用Searcher执行查询,返回匹配的结果集。ScoreDoc表示每个匹配文档的...

    Lucene5写的全文搜索的demo,包括创建索引和搜索

    从索引的构建到查询的执行,每个步骤都涉及到对 Lucene API 的深入理解。通过学习这个示例,开发者可以进一步了解 Lucene 的工作原理,并将其应用到自己的项目中,提升搜索功能的效率和用户体验。

    lucene入门小例子

    这个“lucene入门小例子”很可能是为了帮助初学者理解并掌握Lucene的基本用法而设计的一系列示例代码。 Lucene的核心概念包括索引、文档、字段和查询。首先,你需要理解索引的概念,它类似于传统数据库中的索引,但...

    lucene学习入门程序

    **Lucene学习入门程序** Lucene是一个开源的全文搜索引擎库,由Apache软件基金会开发并维护。它是Java编写,可以被集成到各种应用中,提供强大的文本检索功能。本程序是针对初学者设计的,旨在帮助开发者快速理解并...

    luke--- lucene索引数据查看器

    - **教学**:对于学习Lucene的初学者,Luke提供了直观的示例,帮助理解Lucene的工作原理。 - **性能优化**:通过观察查询执行和分析过程,可以优化查询语句和索引配置。 ### 4. 注意事项 - Luke只能查看Lucene...

    .NET lucene 源代码

    描述中提到的“简单易用”,揭示了Lucene的核心特性之一,即它对开发者友好,易于集成到项目中。 首先,我们需要了解Lucene的基本概念。Lucene最初是Java平台上的一个开源项目,由Apache软件基金会维护。后来,为了...

    Lucene常用的Demo

    本篇文章将深入探讨Lucene的几个常见示例,包括`LuceneDemo`、`LuceneZJ`、`Lucene_HelloWorld`,帮助初学者快速理解Lucene的基本操作。 1. **Lucene_HelloWorld** 这个示例是入门Lucene的首选,它展示了如何创建...

    lucene3.6的入门案例

    通过对这个案例的学习,你可以掌握 Lucene 的基本操作,为进一步深入学习和应用打下基础。 在实际项目中,你可能需要考虑更多细节,如错误处理、多线程索引、优化索引性能、处理大量数据等。此外,随着 Lucene 版本...

    lucene.net2.9.4源码版

    总结,Lucene.NET 2.9.4源码版为.NET开发者提供了宝贵的资源,通过阅读源码,我们可以学习到全文搜索引擎的设计思想,理解其内部工作流程,从而在实际项目中更加自如地运用Lucene.NET,提高搜索功能的效率和用户体验...

    最新全文检索 lucene-5.2.1 入门经典实例

    《最新全文检索 Lucene-5.2.1 入门经典实例》 Lucene是一个开源的全文检索库,由Apache软件基金...通过学习和实践这些经典实例,开发者能够掌握如何利用Lucene构建高效的全文检索系统,提升数据的可搜寻性和用户体验。

Global site tag (gtag.js) - Google Analytics