《Lucene天书》 Lucene的文件系统

Lucene的文件系统分为内存和硬盘两个部分,文件逻辑组织方式暂且不提,本文将关注其物理结构,包括它在内存中如何存放,以及如何写入硬盘。

目录
一、相关类
   1.1 Directory
   1.2 IndexInput和IndexOutput
   1.3 RAMFile
二、索引概述
   2.1 IndexOutput
 2.2 RAMOutputStream和RAMFile
   2.3 内存文件是如何写入硬盘的

一、相关类

1.1 Directory
一个Directory在Lucene系统中可以被称为“一份索引”,可以有许多份索引共同提供搜索数据源,而一个Directory就是对其每份索引的描述。它可以存放在内存中,也可以存放于硬盘上。存放在内存中的时候,是使用它子类RAMDirectory的实例,存放在硬盘上的时候是使用FSDirectory的实例。

图 1.1.1 Directory类图

1.2 IndexInput和IndexOutput
IndexInput负责读取,IndexOutput负责写入。其子类负责具体的工作。这里暂且不多讲。


图1.2.1 IndexOutput和IndexInput

1.3 RAMFile
RAMFile是Lucene文件系统内存文件的基本单位。一个Directory可以包含N个RAMFile(N >= 2)。

二、索引概述
这里不讨论索引的逻辑结构,而只单纯地看索引是如何在内存中存储,如何持久化到硬盘。


图 2.1 索引过程

图2.1体现整个过程。首先调用IndexWriter类的AddDocument方法,这个是外部调用,走入内部,是由IndexWriter调用了DocumentWriter的AddDocument方法。然后DocumentWriter完成调用自身的UpdateDocument,ProcessDocument,ProcessField方法,再转入FieldWriter的WriteField方法,这个方法又调用了IndexOutput里WriteInt或者其它一些按类型写入的方法,最终由RAMOutputStream调用自身的WriteByte写入内存。(IndexOutput里的方法实际存在于RAMOutputStream的实例。)

2.1 IndexOutput
IndexOutput主要定义了一些按类型写入的方法,最终都会走向虚方法WriteByte。这些方法在我写的解读Lucene中都有讲到。值得一提的是WriteChars方法,这个方法看似很复杂,但是其完成的功能却很简单,其实是做了.Net Framework中的Encoding.UTF8.GetBytes方法的工作。看下代码2.1.1和2.1.2的相似之处就可以明白。(代码2.1.1摘自Lucene IndexOutput源码,2.1.2摘自.Net Framework UTF8Encoding类源码。其自己实现是因为翻译自Java版本。)

代码 2.1.1

 

代码 2.1.2


2.2 RAMOutputStream和RAMFile
RAMOutputStream是IndexOutput的一个子类,其主要点在于三个元素。
1、BUFFER_SIZE 是其缓冲片段的长度;
2、RAMFile 内存文件实例;
3、它的一些方法。
它的方法最终都是完成把数据写入缓冲片段,再把缓冲片段存入RAMFile的实例。它们之间就是这个关系。
RAMOutputStream需要写入数据,最终会写入一个byte数组,这个数组的长度就是BUFFER_SIZE,由RAMOutputStream调用RAMFile的AddBuffer方法负责创建这个数组,同时把这个数组作为一个节点存入RAMFile的ArrayList。也就是说RAMFile代表的一个内存文件,实际上是一个ArrayList数组。而ArrayList数组的每个索引又都由一个byte数组组成,这个byte数组的长度是BUFFER_SIZE。RAMOutputStream的WriteByte方法负责把数据写入byte数组。(看到这个是不是觉得Lucene的文件系统根本就不是什么天书嘛,也是很好理解的嘛,呵呵。)

2.3 内存文件如何写入硬盘的
Lucene文件系统在硬盘的表现实例就是FSDirectory。这个类会负责创建其文件系统所需的描述性文件和数据文件。而具体写入硬盘的工作是由它的内嵌类FSIndexOutput来完成的。这也就是我们的图1.2.1没有描绘到这个类的原因,这个类继承自BufferedIndexOutput。BufferedIndexOutput大体上与RAMOutputStream差不多,区别在于其Flush方法与会调用到FSIndexOutput的FlushBuffer方法,最终把RAMFile的数据写入硬盘文件。

时间原因,这里就不详细介绍了,感兴趣的朋友可以自己去实验一下。

______________________________________________________________________________________________
2009-2-18 by yurow
@ http://birdshover.cnblogs.com

posted @ 2009-02-18 14:55  Birdshover  阅读(5195)  评论(7编辑  收藏  举报