本帖最后由 nettman 于 2015-4-16 22:39 编辑
问题导读:
1、如何利用lucene来实现索引的管理?
2、如何实现索引的单例模式?
3、内存重读线程的配置参数如何配置?
接上篇:基于lucene的案例开发13:实现实时索引基本原理
在前一篇博客中,对实时索引的实现原理做了一些简单的介绍,这里就介绍下,如何利用Lucene来实现索引的管理(Lucene中已经实现了大部分的功能,我们只需要对其再次封装即可)。
逐个击破
在Lucene4.3.1中,实现实时索引时,需要将IndexWrite的相关操作委托给TrackingIndexWriter来处理,具体代码实现如下:
ps:关于如何创建索引这里就不再介绍了,可以参照之前的博客或者该博客后面的完整代码。
- this.trackingIndexWriter = new TrackingIndexWriter(this.indexWriter);
复制代码
同时初始化索引管理对象,代码如下:
- this.nrtManager = new NRTManager(this.trackingIndexWriter, new SearcherFactory());
复制代码
到这里还需要开启两个守护线程:内存索引重读线程和内存数据commit线程。内存索引重读线程执行的频率也就是实时索引的时差,由于内存中的数据不会太多,所以这个延时一般也就是在十几毫秒左右;内存数据commit线程是将内存中的数据写到磁盘上,不至于数据丢失,如果研究过Lucene源码的童鞋也许会发现,即使你不执行commit操作,到内存中的数据达到一定的程度,也会将一部分数据写到磁盘上,只不过重启服务这部分数据就丢失了同时还会造成一系列的问题, 这个地址下就是commit线程死掉之后造成的一系列问题,感兴趣的童鞋可以了解下。 内存重读线程我们只需要配置下参数启动即可,代码如下:
- this.nrtManagerReopenThread = new NRTManagerReopenThread(this.nrtManager, indexReopenMaxStaleSec, indexReopenMinStaleSec);
- this.nrtManagerReopenThread.setName("NRTManager Reopen Thread");
- this.nrtManagerReopenThread.setPriority(Math.min(Thread.currentThread().getPriority()+2, Thread.MAX_PRIORITY));
- this.nrtManagerReopenThread.setDaemon(true);
- this.nrtManagerReopenThread.start();
复制代码
内存数据commit线程需要自己写代码实现,然后启动该线程即可,代码如下:- private class IndexCommitThread extends Thread{
- private boolean flag;
- public IndexCommitThread(String name){
- super(name);
- }
-
- @SuppressWarnings("deprecation")
- public void run(){
- flag = true;
- while(flag) {
- try {
- indexWriter.commit();
- if (bprint) {
- System.out.println(new Date().toLocaleString() + "\t" + IndexManagerName + "\tcommit");
- }
- TimeUnit.SECONDS.sleep(indexCommitSeconds);
- } catch (IOException e) {
- e.printStackTrace();
- } catch (InterruptedException e1) {
- e1.printStackTrace();
- }
- }
- }
- }
复制代码
- this.indexCommitThread = new IndexCommitThread(IndexManagerName + "Index Commit Thread");
- this.indexCommitThread.setDaemon(true);
- this.indexCommitThread.start();
复制代码
那又如何像普通的索引那样使用IndexSearcher呢?当然NrtManager类也提供了相关的方法,可以获取最新可用的IndexSearcher,代码如下:- public IndexSearcher getIndexSearcher(){
- try {
- return this.nrtManager.acquire();
- } catch (IOException e) {
- e.printStackTrace();
- return null;
- }
- }
复制代码
当然在使用之后别忘记释放,代码如下:- public void release(IndexSearcher searcher){
- try {
- nrtManager.release(searcher);
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
复制代码
另类单例模式
在之前的博客中,我也多次提到,加载索引是一个相当消耗资源的事情,所以我们不可能每一次索引操作都加载一次索引,所以我们就必须使用单例模式来实现IndexManager类。这里的单例模式又和我们常见的单例模式有所区别,普通的单例模式该类只有一个对象,这里的单例模式是该类有多个对象,下面就简单的介绍下此处另类的单例模式。
通过前一篇博客最后,你也许会注意到,系统中关于索引的配置信息是存在HashSet对象中,这也就是说这里IndexManager类会实例化多少次取决于HashSet对象,也就是你配置文件让他实例化多少次就会实例化多少次。既然这样,怎么还能叫单例模式呢?这里的单例是索引的单例,也就是说一个索引只有一个IndexManager对象,不会存在两个IndexManager对象去操作同一个索引的情况。具体代码实现如下:
- /**
- * Initialization on Demand Holder式初始化IndexManager
- */
- private static class LazyLoadIndexManager {
- private static final HashMap<String, IndexManager> indexManager = new HashMap<String, IndexManager>();
-
- static {
- for (ConfigBean configBean : IndexConfig.getConfigBean()) {
- indexManager.put(configBean.getIndexName(), new IndexManager(configBean));
- }
- }
- }
-
- /**
- *@Description: IndexManager私有构造方法
- *@Author: lulei
- *@Version: 1.1.0
- */
- private IndexManager(ConfigBean configBean){
- //...
- }
- public static IndexManager getIndexManager(String indexName){
- return LazyLoadIndexManager.indexManager.get(indexName);
- }
复制代码
这样我们就可以通过索引名获取到该索引的IndexManager对象。
庐山真面目
说了这么多,下面就把IndexManager的源码附在最后,感兴趣的童鞋可以试试(里面还有一些其他的方法,相信不用介绍也都可以看的懂)
复制代码
相关内容:
基于lucene的案例开发1:lucene初始认知
基于lucene的案例开发2:索引数学模型
基于lucene的案例开发3:索引文件结构
基于lucene的案例开发4:创建索引
基于lucene的案例开发5:搜索索引
基于lucene的案例开发6:分词器介绍
基于lucene的案例开发7:Query查询
基于lucene的案例开发8:IndexSearcher中检索方法
基于lucene的案例开发9:案例初识
基于lucene的案例开发10:搜索后台基础,JsonUtil & XmlUtil类介绍
基于lucene的案例开发11:项目常用类ClassUtil & CharsetUtil介绍
基于lucene的案例开发12:数据库连接池
基于lucene的案例开发13:实现实时索引基本原理
基于lucene的案例开发14:实时索引管理类IndexManager
基于lucene的案例开发15:实时索引的检索
基于lucene的案例开发16:实时索引的修改
基于lucene的案例开发17:查询语句创建PackQuery
基于lucene的案例开发18:纵横小说更新列表页抓取
基于lucene的案例开发19:纵横小说简介页采集
基于lucene的案例开发20:纵横小说章节列表采集
基于lucene的案例开发21:纵横小说阅读页采集
资料来源: http://blog.csdn.net/xiaojimanman/article/details/44015983
|