分享

基于lucene的案例开发13:实现实时索引基本原理

本帖最后由 nettman 于 2015-4-16 22:39 编辑
问题导读:
1、实时索引基本原理是什么?
2、ConfigBean类都定义了索引的哪些基本属性?
3、在lucene系统刚启动时候,存在哪两个索引?



接上篇:


基本原理
      在前面的博客中也说过,程序初始话索引文件是十分消耗系统资源的,因此要想实现实时索引就不能实时的去修改索引文件、重新加载索引文件,就必须考虑如何使用内存来实现这实时索引;在Lucene4.3.1版本(之前的版本也有,但是在后面的版本中就将NRT*相关的类删除了)中NRT*相关类就提供了创建实时索引(伪实时索引)的相关方法,将IndexWrite的相关操作委托给TrackingIndexWriter来处理,实现了内存索引和硬盘索引的结合,通过NRTManager为外部提供可用的索引,当然,在执行commit(之前创建索引中有相关介绍)操作之前,操作的数据都是存在内存中,一旦宕机或者服务重,这些数据都将丢失,因此就需要自己添加一个守护线程去不断的执行commit操作(commit操作十分消耗系统资源,索引不可能每一次修改都去执行该操作)。下面就通过几个简单的图来介绍一下实时索引的实现原理:
      在系统刚启动时候,存在两个索引:内存索引、硬盘索引,当然此时内存索引中是没有任何数据的,结构如下图所示:

20150228102814556.png


      在系统运行过程中,一旦有索引的增加、删除、修改等操作,这些操作都是操作内存索引,而不是硬盘索引,如下图所示:
20150228102819002.png
      当程序主动执行commit操作时,这是会将内存索引复制一份,我们称之为合并索引,同时将内存索引清空,用于之后的索引操作,此时系统中就存在内存索引、合并索引、硬盘索引,在想外提供服务的同时,也会将合并索引中的数据写入硬盘,如下图所示:

20150228102803686.png

      当合并索引中的数据已经全部写入硬盘之后,程序会对硬盘索引重读,形成新的IndexReader,在新的硬盘IndexReader替换旧的硬盘IndexReader时,删除合并索引的IndexReader,这样系统又重新回到最初的状态(当然此时内存索引中可能会有数据),如下图所示:


20150228102808662.png



      如此反复,一个实时索引的系统也就算完成了,当然这里也会有一定的风险,就是在宕机时可能会丢失一部分的数据。关于这个问题,如果数据准确度要求不是太高的话可以忽略,毕竟这种情况发生的概率太小了;如果对数据的准确度要求特别高的话,可以通过添加输出日志来完成。
      ps:Lucene内部的实现逻辑比上面复杂的多,这里只是简单的介绍一下实现原理,如要深入了解,还请详细阅读相关书籍、源码。

配置类
      在这篇博客中就先把这个系列的实时索引的配置类介绍以下,后面就不再介绍了。

ConfigBean

      ConfigBean类中,定义了一些索引的基本属性,如:索引名、硬盘存储位置、采用的分词器、commit操作执行频率、内存索引重读频率等,具体代码如下:
  1. /**   
  2.      *@Description:  索引基础配置属性
  3.      */  
  4.     package com.lulei.lucene.index.model;  
  5.       
  6.     import org.apache.lucene.analysis.Analyzer;  
  7.     import org.apache.lucene.analysis.standard.StandardAnalyzer;  
  8.     import org.apache.lucene.util.Version;  
  9.       
  10.     public class ConfigBean {  
  11.         // 分词器  
  12.         private Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_43);  
  13.         // 索引地址  
  14.         private String indexPath = "/index/";  
  15.         private double indexReopenMaxStaleSec = 10;  
  16.         private double indexReopenMinStaleSec = 0.025;  
  17.         // 索引commit时间  
  18.         private int indexCommitSeconds = 60;  
  19.         // 索引名称  
  20.         private String indexName = "index";  
  21.         //commit时是否输出相关信息  
  22.         private boolean bprint = true;  
  23.          
  24.         public Analyzer getAnalyzer() {  
  25.             return analyzer;  
  26.         }  
  27.         public void setAnalyzer(Analyzer analyzer) {  
  28.             this.analyzer = analyzer;  
  29.         }  
  30.         public String getIndexPath() {  
  31.             return indexPath;  
  32.         }  
  33.         public void setIndexPath(String indexPath) {  
  34.             if (!(indexPath.endsWith("\") || indexPath.endsWith("/"))) {  
  35.                 indexPath += "/";  
  36.             }  
  37.             this.indexPath = indexPath;  
  38.         }  
  39.         public double getIndexReopenMaxStaleSec() {  
  40.             return indexReopenMaxStaleSec;  
  41.         }  
  42.         public void setIndexReopenMaxStaleSec(double indexReopenMaxStaleSec) {  
  43.             this.indexReopenMaxStaleSec = indexReopenMaxStaleSec;  
  44.         }  
  45.         public double getIndexReopenMinStaleSec() {  
  46.             return indexReopenMinStaleSec;  
  47.         }  
  48.         public void setIndexReopenMinStaleSec(double indexReopenMinStaleSec) {  
  49.             this.indexReopenMinStaleSec = indexReopenMinStaleSec;  
  50.         }  
  51.         public int getIndexCommitSeconds() {  
  52.             return indexCommitSeconds;  
  53.         }  
  54.         public void setIndexCommitSeconds(int indexCommitSeconds) {  
  55.             this.indexCommitSeconds = indexCommitSeconds;  
  56.         }  
  57.         public String getIndexName() {  
  58.             return indexName;  
  59.         }  
  60.         public void setIndexName(String indexName) {  
  61.             this.indexName = indexName;  
  62.         }  
  63.         public boolean isBprint() {  
  64.             return bprint;  
  65.         }  
  66.         public void setBprint(boolean bprint) {  
  67.             this.bprint = bprint;  
  68.         }  
  69.     }  
复制代码
IndexConfig

      在一个系统中并不一定只存在一个索引,也可能会是多个,所以又添加了一个IndexConfig类,具体代码如下:
  1. /**   
  2.      *@Description: 索引的相关配置参数
  3.      */   
  4.     package com.lulei.lucene.index.model;   
  5.       
  6.     import java.util.HashSet;  
  7.       
  8.     public class IndexConfig {  
  9.         //配置参数  
  10.         private static HashSet<ConfigBean> configBean = null;  
  11.          
  12.         //默认的配置  
  13.         private static class LazyLoadIndexConfig {  
  14.             private static final HashSet<ConfigBean> configBeanDefault = new HashSet<ConfigBean>();  
  15.              static {  
  16.                  ConfigBean configBean = new ConfigBean();  
  17.                  configBeanDefault.add(configBean);  
  18.              }  
  19.         }  
  20.       
  21.         public static HashSet<ConfigBean> getConfigBean() {  
  22.             //如果未对IndexConfig初始化,则使用默认配置  
  23.             if (configBean == null) {  
  24.                 configBean = LazyLoadIndexConfig.configBeanDefault;  
  25.             }  
  26.             return configBean;  
  27.         }  
  28.       
  29.         public static void setConfigBean(HashSet<ConfigBean> configBean) {  
  30.             IndexConfig.configBean = configBean;  
  31.         }  
  32.     }  
复制代码






相关内容:
基于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://www.llwjy.com/blogdetail/63d4c488a2cccb5851c0498d374951c9.html








欢迎加入about云群371358502、39327136,云计算爱好者群,亦可关注about云腾讯认证空间||关注本站微信

已有(1)人评论

跳转到指定楼层
zhujun182104906 发表于 2015-4-14 22:09:24
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条