网上的解释真的不能看,全是错的,因为生产中遇到的一次问题对该原理研究了3天,查看了大量书籍,官方文档终于有了较为深刻的认识
Solr的提交方式只有两种,标准提交(硬提交,hard commit)和软提交(soft commit),说三种的错误
Hard commit
1.默认的提交即硬提交,commit之后会立刻将文档同步到硬盘,在开启新搜索器之前会阻塞,直到同步完成
2.默认情况下commit后会开启一个新搜索器(newSearcher),然后进行预热,预热完成后顶替旧搜索器,使旧缓存失效,但是开启新searcher及预热的过程(IO消耗)耗费资源过大,且可能被阻塞,所以应尽量避免在高峰期开启newsearcher,搜索器同一时间只能有一个处于active状态
3.为了避免频繁commit,solr提供了autocommit功能,可以设置每隔多久提交一次,或者待提交文档量达到阀值提交一次,并且可定义是否在提交后开启新的搜索器,若不开启,则缓存不能够被刷新,新更新文档不能够被实时读取到
<autoCommit>
<!--最大文档数量-->
<maxDocs>1000</maxDocs>
<!--最大间隔时间-->
<maxTime>${solr.autoCommit.maxTime:300000}</maxTime>
<!--提交后是否开启新搜索器-->
<openSearcher>false</openSearcher>
</autoCommit>
Soft commit
1.软提交是将文档提交到内存,并不实时写入硬盘,减少了耗时的I/O操作
2.为了保证实时搜索,solr在软提交基础上引入了近实时搜索(NRT),NRT并不会被文档更新所阻塞,也不会等待文档合并完成再打开一个搜索器(以下摘自官方文档)
Near Real Time (NRT) search means that documents are available for search almost immediately after being indexed.
This allows additions and updates to documents to be seen in 'near' real time. Solr does not block updates while a commit is in progress. Nor does it wait for background merges to complete before opening a new search of indexes and returning.
With NRT, you can modify a commit command to be a soft commit, which avoids parts of a standard commit that can be costly. You will still want to do standard commits to ensure that documents are in stable storage, but soft commits let you see a very near real time view of the index in the meantime.
3.在lucene4.x 之前,solr采用NRTManager实现NRT,之后使用ControlledRealTimeReopenThread实现,它通过IndexWriter对象来监控内存中的文档变化,从而得到最新的文档信息,该过程既不需要高耗时的I/O操作,也不需要刷新搜索器,所以非常之快,耗费资源很少
4.所以近实时搜索(NRT)是软提交的一个特性
5.同样的软提交也支持自动提交的方式,配置如下
<autoSoftCommit>
<maxDocs>1000</maxDocs>
<maxTime>${solr.autoSoftCommit.maxTime:30000}</maxTime>
</autoSoftCommit>
5.这两种提交方式并不冲突,试想我们程序使用了软提交,但何时可以把数据真正同步到磁盘呢?这时候就可以两者结合达到目的
<autoCommit>
<maxTime>${solr.autoCommit.maxTime:300000}</maxTime>
<openSearcher>false</openSearcher>
</autoCommit>
<autoSoftCommit>
<maxTime>${solr.autoSoftCommit.maxTime:5000}</maxTime>
</autoSoftCommit>
我们设置每隔5000ms进行一次软提交,文档存入了内存,也可以实时搜索,然后每隔300000ms又会进行进行一次硬提交,同步到磁盘,无需刷新Searcher,如此两者兼顾
6.在配置文件中配置后,在客户端就不需要维护提交方式和提交时间了
争论及疑问
1.很多人说由于软提交不及时写入硬盘,所以在jvm崩溃时会丢失部分数据,但其实不会,因为软提交和硬提交在commit时都会记录下操作log,若发生崩溃,会在重启时会从log恢复,这点很像mysql的事务日志操作
2.若maxDocs和maxTime都配置了,则那个条件先到就按那个执行,官方建议使用maxTime,因为solr文档较多,通常更新量也大,使用maxTime可能更能减少提交的频次,但在此建议根据实际情况来决定
3.commit操作后,可执行optimize操作,该操作会合并索引碎片,合并后索引性能会有所提升,但该操作消耗较大,每晚定时操作一次即可