乐趣区

关于lucene:Lucene基本知识

Lucene 采纳了基于倒排表的设计原理,能够十分高效的实现文本查找,在底层采纳了分段的存储模式,使它在读写时简直完全避免锁的呈现,大大晋升了读写性能。

外围模块

lucene 的写流程和读流程如图所示。

其中,虚线箭头 (a,b,c,d) 示意写索引的次要过程,实线箭头 (1-9) 示意查问的次要过程。
lucene 的次要模块(可联合上图)

  1. analysis 模块:次要负责词法剖析及语言解决,也就是常说的分词,通过该模块可最终造成存储或搜寻的最小单元 Term。
  2. index 模块:次要负责索引的创立工作。
  3. store 模块:次要负责索引的读写,次要是对文件的一些操作,其次要目标是形象出和平台文件系统无关的存储。
  4. queryParser:次要负责语法分析,把咱们的查问语句生成 Lucene 底层能够辨认的条件。
  5. search 模块:次要负责对索引的搜寻工作
  6. similarity 模块:次要负责相差性打分和排序的实现

外围术语

  1. Term:是索引里最小的存储和查问单元,对于英文来说个别指一个单词,对于中文来说个别指一个分词后的词。
  2. 词典 (Term Dictionary):是 Term 的汇合。词典的数据结构有多种,比方排序数组通过二分查找来检索数据;HashMap 较排序数据快但占用空间更多;fst(finite-state transducer) 有更高的数据压缩率与查问效率。fst 是默认的数据结构。
  3. 倒排表:一篇文章通常由多个词组成,倒排表记录的是某个词在哪些文章中呈现过
  4. 正向信息:原始的文档信息,能够用来做排序,聚合与展现等。
  5. 段(segment):索引中最小的独立存储单元。一个索引文件由一个或多个段组成。在 Lucene 中的段有不变性,段一旦生成,在其上只能有读 rket,不能有写操作

Lucene 的底层存储格局如下图所示。其中的字典就是 Term 汇合。词典中的 Term 指向的文档链表的汇合叫倒排表。词典与倒排表是实现疾速检索的重要根底,它们是分两局部存储的,在倒排表中岂但存储了文档编号,还存储了词频等信息。

检索形式

在 Lucene 的查问过程中次要检索形式有上面四种。

  1. 单个词查问
    指对一个 Term 进行查问,比方查找蕴含字符串‘lucene’ 的文档,则只须要词典中找到 Term ‘lucene’,再取得在倒排表中对应的文档链表即可。
  2. AND
    批对多个汇合求交加。比方查找既蕴含字符串‘lucene’ 又蕴含字符串‘solr‘的文档,则查找步骤如下:
    1) 在词典中找到 Term ‘lucene’,失去‘lucene‘对应的文档链表。
    2) 在词典中找到 Term ‘solr’,失去‘solr‘对应的文档链表。
    3) 合并链表,对两个文档链表做交加运算。
  3. OR
    指对多个汇合求并集。比方,若要查找蕴含字符串“lucene”或者蕴含字符串“solr”的文档,则查找步骤如下。
    1) 在词典中找到 Term“lucene”,失去“lucene”对应的文档链表。
    2) 在词典中找到 Term“solr”,失去“solr”对应的文档链表。
    3) 合并链表,对两个文档链表做并集运算,合并后的后果蕴含“lucene”或者蕴含“solr”。
  4. NOT
    指对多个汇合求差集。比方,若要查找蕴含字符串“solr”但不蕴含字符串“lucene”的文档,则查找步骤如下。
    1) 在词典中找到 Term“lucene”,失去“lucene”对应的文档链表。
    2) 在词典中找到 Term“solr”,失去“solr”对应的文档链表。
    3) 合并链表,对两个文档链表做差集运算,用蕴含“solr”的文档集减去蕴含“lucene”的文档集,运算后的后果就是蕴含“solr”但不蕴含“lucene”.

通过上述四种查问形式,咱们能够晓得,因为 Lucene 是以倒排表的模式存储的,所以在 Lucene 的查找过程中只需在词典中找到这些 Term,依据 Term 取得文档链表,而后依据具体的查问条件对链表进行交,并,差等操作,就能够精确地查到咱们想要的后果。

分段存储

晚期全文检索为整个文档汇合建设一个很大的倒排索引并将其写入磁盘,如果有更新,就须要从新创立一个索引来代替原来的索引。显然这种形式在数据量大的时候效率很低。
当初,在搜寻中引入了段的概念,每个段都是一个独立的可被搜寻的数据集,并且段具备不可变性,一旦索引的数据被写入磁盘就不可再批改。
在分段思维下,对数据写操作的过程如下:

  • 新增。当有新的数据须要创立索引时,因为段的不变性,所以抉择新建一个段来存储新增的数据。
  • 删除。当须要删除数据时,因为数据的在的段只可读不可写,所以 Lucene 在索引文件下新增了了一个.del 文件,用来专门存储被删除的数据 id,当查问时,被删除的数据还是能够被查到,只是在进行文档链表合并时,才将曾经删除的数据过滤掉。被删除的数据在进行段合并时才会真正被移除。
  • 更新。更新操作其实就是删除和新增的组合,先在.del 文件中记录旧数据,再在新的段中增加一条更新后的数据。

段不变的长处

  1. 不须要锁。因为数据不会更新,所以不必思考多线程下的读写不统一问题
  2. 能够常驻外在。段在被加载到外在后,因为不变性,所以只有外在的空间足够大,就能够长时间驻存,大部分查问申请会间接拜访内存而不须要拜访磁盘
  3. 绑在敌对。在段的申明周期内始终无效,不须要在每次数据更新时被重建
  4. 增量创立。分段能够做到增量创立索引,能够轻量级对数据进行更新,因为每次创立的老本很低,所以能够频繁地更新数据,使零碎靠近实时更新。

段不变的毛病

  1. 空间节约。对数据进行删除时,旧数据不会被马上删除,只有到段合并时才会移除,这样会节约大量空间
  2. 更新时节约空间。更新是由新建与删除两个动作组成,也会节约不少空间
  3. 服务器资源耗费大。因为索引具备不变性,所以每次更新数据时都须要新增一个段来存储数据。当段的数量过多时,对服务器的资源(如文件句柄)的耗费十分大,也会影响到查问性能。
  4. 查问时须要过滤删除数据。在查问后须要对曾经删除的旧数据进行过滤,会减少查问的累赘。

为了晋升写的性能。Lucene 并没有每新增一条数据就减少一个段,而是采纳提早写的策略,每当有新增的数据时,就将其先写入内存中,而后批量写入磁盘中。若有一个段被写到磁盘,就会生成一个提交点,提交点就是一个用来记录所有提交后的段信息的文件。一个段一旦领有了提交点,就阐明这个段只有读的权限没写的权限;相同,当段在内存中时,就只有写数据权限而没有读数据权限,所以也就不能被检索了。因而从严格意义上来说 Lucene 或 ES 只能称为准实时的搜索引擎。

写索引流程

  1. 数据被写入时,并没有间接写到磁盘,而是被临时写到内存中,默认是 1 秒,或当内存中的数据量达到肯定阶段,再批量提交到磁盘中。通过提早写策略能够晋升整体写入性能。
  2. 在达到触发条件后,会将内存中缓存的数据一次性写入磁盘,并生成提交点。
  3. 清空内存,期待新的数据写入。

须要留神的是,正因为有提早写,如果呈现断电等状况会呈现失落数据,为此 ES 不回了事务日志,来保障事务平安。

段合并策略

每次新增数据时都会新增一个段,所以工夫长了后会导致索引中存在大量的段,这样会重大耗费服务资源,也会影响逵性能。
咱们晓得索引检索的过程是:查问所有段中满足查问条件的数据,而后对每个段里查问后果集进行合并,所以为了管制索引里段的数量,咱们须要定期进行段合并操作。Lucene 合并段的思路是:依据段的大小将段分组,再将属于同一组的段进行合并。因为对那些特地大的段进行合并须要耗费更多的资源,所以 Lucene 会在段的大小达到肯定规模或段外面的数据达到肯定条数时,不会再进行合并。

类似度打分

Lucene 的查问过程是:首先在词典中查找每个 Term,依据 Term 取得每个 Term 所存在的文档链表,而后依据查问条件对链表做交,并,差等操作,链表合并后的后果就是咱们须要查找的数据。然而,咱们一次查问出很多数据时,这些数据和咱们的查问条件又有多大关系呢?其文本类似度是多少呢?它们是在 similarity 模块实现的。Lucene 最经典的两文本类似度算法:基于向量空间模型的算法和基于概率的算法。。。前面的内容看不太懂了就写到这里,有趣味能够看原文。

退出移动版