Lucene5学习之Directory理解

2023-11-02 01:48

本文主要是介绍Lucene5学习之Directory理解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

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

 

@Overridepublic 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,

或者加裙
一起交流学习!
 

这篇关于Lucene5学习之Directory理解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/327262

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识