lucene在一些数据的写动作的时候,比如insert/update/delete等动作,并不会直接写入到磁盘,而是在内存中生效。然后再由某些条件去触发flush动作,这些动作有addIndexs,forceMerge,forceMergeDeletes,shutdown。还有在Insert和delete之类的动作,超过了LiveIndexWriterConfig.maxBufferedDocs和LiveIndexWriterConfig.ramBufferSizeMB之类的时候都会触发flush动作。当然也可以直接调用flush接口。
索引的flush入口在IndexWriter.flush。或者是上述的一些动作触发。IndexWriter.flush
->IndexWriter.doFLush()
.我们就从doFlush()
方法开始看.代码看着比较多,但真正做flush动作的内容其实就是docWriter.flushAllThreads();;
|
|
很显然,直接看DocWriter.flushAllThreads()
,这里做的事情,其实就把所有要flush的DocumentsWriterPerThread
给拿出来全部轮一遍做doFlush(flushingDWPT)
,flushingDWPT是DocumentsWriterPerThread
类型,是一个代表索引文档的写线程对象。这个方法里才是做真正的flush。
|
|
由此为止,目前的调用链为IndexWriter.doFLush()
->DocWriter.flushAllThreads()
,DocWriter.doFlush(flushingDWPT)
。贴doFlush(flushingDWPT)的代码
。这里做的具体的动作有ticket = ticketQueue.addFlushTicket(flushingDWPT)
;ticketQueue被定义为DocumentsWriterFlushQueue
,用来同步多个flush线程。其中ticketQueue.addFlushTicket(flushingDWPT)
做了flushingDWPT.prepareFlush()
,这里是把一些被标记为删除的数据给提前删除掉了。然后做真正的flush动作flushingDWPT.flush()
.在flush完成后把情况添加到ticketQueue中。
|
|
这里是DocumentsWriterPerThread.flush()
,初始化了一个SegmentWriteState flushState
,flushState
中包含了该分片的所有信息,由 consumer.flush(flushState);
完成把文件的刷入。下面重点看consumer.flush(flushState)
|
|
DefaultIndexingChain.flush(SegmentWriteState state)
是把文件刷入具体的磁盘。这里第一步是writeNorms(state, sortMap);
会把segment的codec格式,索引头,字段域信息,字段规范等等信息写入到索引的_32a.nvd
和_32a.nvm
这两文件中。然后是writeDocValues(state, sortMap);
把docValue写入到数据中,再然后是writePoints(state, sortMap);
,把ponitValues(取代NumericField)写入,这些东西会被写到.dim文件中;接下来storedFieldsConsumer.finish(maxDoc);storedFieldsConsumer.flush(state, sortMap);
会把数据写入到.fdt和.fdx中,这两个文件占了索引存储的大头;termsHash.flush(fieldsToFlush, state, sortMap,normsMergeInstance);
把词元信息写入到.tvd和.tvx文件;docWriter.codec.fieldInfosFormat().write(state.directory, state.segmentInfo, "", state.fieldInfos, IOContext.DEFAULT);
把数据写入.fnm程序。
|
|
到此为止,所有的flush动作结束。一个完成的flush流程为IndexWriter.doFLush()
->DocWriter.flushAllThreads()
->DocWriter.doFlush(flushingDWPT)
->DocumentsWriterPerThread.flush()
->DefaultIndexingChain.flush(SegmentWriteState state)
。最后的DefaultIndexingChain.flush(SegmentWriteState state)
会flush各种数据到lucene的索引文件中。在segment flush完成后,DocumentWriter会尝试合并segment。
索引segment下的文件格式
直接从网上拿了个文件格式对应的文件
文件名 | 后缀 | 描述 |
---|---|---|
Segments File | segments.gen, segments_N | 存储段文件的提交点信息 |
Lock File | write.lock | 文件锁,保证任何时刻只有一个线程可以写入索引 |
Segment Info | .si | 存储每个段文件的元数据信息 |
Compound File | .cfs, .cfe | 复合索引的文件,在系统上虚拟的一个文件,用于频繁的文件句柄 |
Fields | .fnm | 存储域文件的信息 |
Field Index | .fdx | 存储域数据的指针 |
Field Data | .fdt | 存储所有文档的字段信息 |
Term Dictionary | .tim | term字典,存储term信息 |
Term Index | .tip | term字典的索引文件 |
Frequencies | .frq | 词频文件,包含文档列表以及每一个term和其词频 |
Positions | .prx | 位置信息,存储每个term,在索引中的准确位置 |
Norms | .nrm.cfs, .nrm.cfe | 存储文档和域的编码长度以及加权因子 |
Per-Document Values | .dv.cfs, .dv.cfe | 编码除外的额外的打分因素, |
Term Vector Index | .tvx | term向量索引,存储term在文档中的偏移距离 |
Term Vector Documents | .tvd | 包含每个文档向量的信息 |
Term Vector Fields | .tvf | 存储filed级别的向量信息 |
Deleted Documents | .del | 存储索引删除文件的信息 |