最近一直在看Lucene的源码和文档,把看到的一些东西总结一下,整个Lucene的代码也大体的撸了一遍了,Lucene的代码写得真是不错,结构简单明了,扩展性也非常强,基本上所有的模块都是接口型的,几乎都有扩展的可能,并且可以以非侵入式的方式进行扩展,后来的在Lucene之上的Elasticsearch也很好的继承了这一点,扩展性也非常强,当然,Elasticsearch的代码说实在的理解起来没有Lucene的好,感觉太复杂了,不太好理清楚一个逻辑,各种设计模式玩得太6了,反而造成代码不太好理解,一个数据插入的过程,如果没有单步跟踪,生看代码很难理清楚数据流向,这点Lucene就做得好多了,一切以简单为主,等Lucene的代码分析完以后再写写Elasticsearch的代码。
今天开个头,要写好Lucene的代码分析需要好好构思一下整个脉络,今天简单说一下整个文件的结构和两条主脉对应到的文件夹,方便后面的理解。
怎么看源码
一个搜索引擎的索引源代码如何来看呢,一般看代码的话,常见的有两种方式:
- 一种是从入口开始,这种适合于一启动就开始工作的软件,从入口开始可以看到各个模块的加载然后再深入到各个模块上去看具体的实现,最典型的就是Linux的源码了,一般都是从head.s开始,初始化cpu,内存控制器等,然后进入c语言跳到setup函数,巴拉巴拉的,这里就不展开了。这类代码顺着这条路下去可以深入到各个模块中看具体的模块实现,然后通过这个启动接口把所有的模块串起来。当然,对于linux的代码,一般建议从Makefile开始进行代码的阅读,内核代码实在是太过复杂,知道一个启动过程并不能理解代码,并且仅凭个人能力也很难理解全部代码,只能从Makefile角度来理解对应的模块。
- 还有一种就是服务类的代码,比如nginx代码啊,redis的代码啊都是这种,只有当接收到了具体的请求才会出现具体的相应,各个模块是和请求绑定在一起的,这种从入口开始看的话,很多模块是看不到的,需要从数据流的角度来分析这个代码。
而Lucene就是这类代码,Lucene基本上来说对外暴露的是两个接口,一个是索引的插入,一个是query的检索,这属于两个大的数据流,所以从这两个数据流的方向上来看源代码是可以遍历到各个模块的。
Lucene的源码
对于搜索引擎的源码来说,还有一种比较好的方式,就是你在了解了搜索引擎原理的情况下进行代码的阅读会更好。
我们知道,搜索引擎基本上分为以下几个重要的模块:索引部分分成:倒排链结构,倒排字典结构,正排结构;检索部分分成:query分析改写,交集并集查询,复杂聚合查询;除了前面的两部分,一般还会有一个底层的统一存储接口进行操作系统的隔离。Lucene是JAVA写的,操作系统的隔离就不需要了,但是还是有一个统一的存储接口,方便进行存储结构的扩展。
OK,我们就按照上面的模块来看看Lucene的源码,然后这个系列会分别对上述所有模块的源代码进行一下分析。Lucene的核心代码都在core/src/java/org/apache/lucene
这个下面,我们主要的分析也是这个文件夹,不得不说的是Elasticsearch的代码也是在core这个文件夹下面,我之前没怎么搞过java,不知道是模仿Lucene还是java代码都这样。
整体结构
整个lucene的文件夹是这样的,通过上面对搜索引擎模块的描述,我们很快可以通过文件夹的命名知道各个文件夹大体对应的模块:
- codecs,编码解码的,用来对数据进行格式化的,包括对老版本的索引结构的兼容代码都在这,这应该是真实的文档到存储结构的中间映射层
- geo,地理位置信息相关结构的代码,地理位置这个明显是后来加上去的,我猜测是因为按照之前的搜索接口设计应该没考虑到地理位置的,这个结构和其他的有较大的不同不是特别好集成,所以单独列出来了。
- store ,底层封装的那个存储层,实现了各种存储方案。
- analysis ,query的分析和改写
- document,文档结构,一般是支持的文档类型
- index ,索引类,文档被索引的过程就在这里完成
- search,检索类,query被检索的过程就在这里完成
- util ,工具函数,这里有很多重要的数据结构实现的重头戏,如Lucene字典核心的FST算法的代码就在这下面
从上面就可以比较明显的屡出两条脉络来了。
- 一是数据索引的时候,应该是在
document
里面生成一个文档,然后通过index
文件夹里面的索引方法把文档最终存储到store
文件夹中的存储结构中去,存储的时候会通过codecs
下面的代码进行存储的编码。 - 二是数据检索的时候,应该是在
analysis
下面对检索的语句进行分析和改写,然后通过search
文件夹下面的类操作store
存储层取出数据,求数据集合之前的各种交集并集,最后生成结果集返回,在取出数据的时候通过codecs
下面的代码对存储进行解码。
这样一来,整个代码的结构就清楚了,接下来的文章会一步一步的把整个代码分析一下,上面的主脉络如果有说得不对的后面的文章会做修正,今天就算开个头吧,争取每一到两周更新一篇。
如果你觉得不错,欢迎转发给更多人看到,也欢迎关注我的公众号,主要聊聊搜索,推荐,广告技术,还有瞎扯。。文章会在这里首先发出来:)扫描或者搜索微信号XJJ267或者搜索西加加语言就行
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。