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

转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/43982653

http://www.llwjy.com/blogd.php?id=63d4c488a2cccb5851c0498d374951c9

个人的博客小站也搭建成功,网址:www.llwjy.com/blog.php ,欢迎大家来吐槽~

基本原理

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

在系统刚启动时候,存在两个索引:内存索引、硬盘索引,当然此时内存索引中是没有任何数据的,结构如下图所示:

在系统运行过程中,一旦有索引的增加、删除、修改等操作,这些操作都是操作内存索引,而不是硬盘索引,如下图所示:

当程序主动执行commit操作时,这是会将内存索引复制一份,我们称之为合并索引,同时将内存索引清空,用于之后的索引操作,此时系统中就存在内存索引、合并索引、硬盘索引,在想外提供服务的同时,也会将合并索引中的数据写入硬盘,如下图所示:

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

如此反复,一个实时索引的系统也就算完成了,当然这里也会有一定的风险,就是在宕机时可能会丢失一部分的数据。关于这个问题,如果数据准确度要求不是太高的话可以忽略,毕竟这种情况发生的概率太小了;如果对数据的准确度要求特别高的话,可以通过添加输出日志来完成。

ps:Lucene内部的实现逻辑比上面复杂的多,这里只是简单的介绍一下实现原理,如要深入了解,还请详细阅读相关书籍、源码。

配置类

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

ConfigBean

ConfigBean类中,定义了一些索引的基本属性,如:索引名、硬盘存储位置、采用的分词器、commit操作执行频率、内存索引重读频率等,具体代码如下:

/**
 *@Description:  索引基础配置属性
 */
package com.lulei.lucene.index.model;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.util.Version;

public class ConfigBean {
	// 分词器
	private Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_43);
	// 索引地址
	private String indexPath = "/index/";
	private double indexReopenMaxStaleSec = 10;
	private double indexReopenMinStaleSec = 0.025;
	// 索引commit时间
	private int indexCommitSeconds = 60;
	// 索引名称
	private String indexName = "index";
	//commit时是否输出相关信息
	private boolean bprint = true;

	public Analyzer getAnalyzer() {
		return analyzer;
	}
	public void setAnalyzer(Analyzer analyzer) {
		this.analyzer = analyzer;
	}
	public String getIndexPath() {
		return indexPath;
	}
	public void setIndexPath(String indexPath) {
		if (!(indexPath.endsWith("\\") || indexPath.endsWith("/"))) {
			indexPath += "/";
		}
		this.indexPath = indexPath;
	}
	public double getIndexReopenMaxStaleSec() {
		return indexReopenMaxStaleSec;
	}
	public void setIndexReopenMaxStaleSec(double indexReopenMaxStaleSec) {
		this.indexReopenMaxStaleSec = indexReopenMaxStaleSec;
	}
	public double getIndexReopenMinStaleSec() {
		return indexReopenMinStaleSec;
	}
	public void setIndexReopenMinStaleSec(double indexReopenMinStaleSec) {
		this.indexReopenMinStaleSec = indexReopenMinStaleSec;
	}
	public int getIndexCommitSeconds() {
		return indexCommitSeconds;
	}
	public void setIndexCommitSeconds(int indexCommitSeconds) {
		this.indexCommitSeconds = indexCommitSeconds;
	}
	public String getIndexName() {
		return indexName;
	}
	public void setIndexName(String indexName) {
		this.indexName = indexName;
	}
	public boolean isBprint() {
		return bprint;
	}
	public void setBprint(boolean bprint) {
		this.bprint = bprint;
	}
}

IndexConfig

在一个系统中并不一定只存在一个索引,也可能会是多个,所以又添加了一个IndexConfig类,具体代码如下:

 /**
 *@Description: 索引的相关配置参数
 */
package com.lulei.lucene.index.model;  

import java.util.HashSet;

public class IndexConfig {
	//配置参数
	private static HashSet<ConfigBean> configBean = null;

	//默认的配置
	private static class LazyLoadIndexConfig {
		private static final HashSet<ConfigBean> configBeanDefault = new HashSet<ConfigBean>();
		 static {
			 ConfigBean configBean = new ConfigBean();
			 configBeanDefault.add(configBean);
		 }
	}

	public static HashSet<ConfigBean> getConfigBean() {
		//如果未对IndexConfig初始化,则使用默认配置
		if (configBean == null) {
			configBean = LazyLoadIndexConfig.configBeanDefault;
		}
		return configBean;
	}

	public static void setConfigBean(HashSet<ConfigBean> configBean) {
		IndexConfig.configBean = configBean;
	}
}

ps:最近发现其他网站可能会对博客转载,上面并没有源链接,如想查看更多关于 基于lucene的案例开发点击这里。或访问网址http://blog.csdn.net/xiaojimanman/article/category/2841877 或 http://www.llwjy.com/blog.php

时间: 2024-12-14 12:51:33

基于lucene的案例开发:实现实时索引基本原理的相关文章

基于lucene的案例开发:实时索引的检索

转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/44279753 http://www.llwjy.com/blogdetail/31bb705106379feaf6d31b58dd777be6.html 个人博客小站搭建成功,网址 www.llwjy.com,欢迎大家来吐槽~ 在前面的博客中,我们已经介绍了IndexSearcher中的检索方法,也介绍了如何基于lucene中的NRT*类去创建实时索引,在这篇博客中我们就重点介

基于lucene的案例开发:实时索引的修改

转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/44280311 http://www.llwjy.com/blogdetail/e42fa5c3097f4964fca0fdfe7cd7a9a2.html 个人的博客小站已经上线了,网址 www.llwjy.com,欢迎大家来吐槽~ 上一篇博客已经介绍了实时索引的检索功能,这个就相当于数据的的查询功能,我们都知道数据库的增删改查是最常用的四个功能,实时索引也是一样,他也有增删改查

基于lucene的案例开发:创建索引

转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/42872711 从这篇博客开始,不论是API介绍还是后面的案例开发,都是基于 lucene4.3.1 这个版本,Lucene4.3.1 下载请点击这里, Lucene其他版本下载请点击这里,Lucene4.3.1官方API文档请点击这里. 创建索引demo 在开始介绍之前,先看一个简单的索引创建demo程序: /** *@Description: 索引创建demo */ pack

基于lucene的案例开发:搜索索引

转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/42884921 此事例中的索引数据来自于上一篇博客创建的索引,索引中包含两篇文档,每一篇文档中有两个域 name . content . 索引搜索demo 还是老样子在介绍之前先看一个简单索引搜索 demo程序. /** *@Description: 索引检索demo */ package com.lulei.lucene.study; import java.io.File;

基于lucene的案例开发:实时索引管理类IndexManager

转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/44015983 http://www.llwjy.com/blogd.php?id=5757ce8c007754704b563dd6a47ca1ca 个人的博客小站也搭建成功,网址:www.llwjy.com/blog.php ,欢迎大家来吐槽~ 在前一篇博客中,对实时索引的实现原理做了一些简单的介绍,这里就介绍下,如何利用Lucene来实现索引的管理(Lucene中已经实现了大

基于lucene的案例开发:案例初识

转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/43192055 首先抱歉,这几天在准备案例的整体框架设计,所以更新就断了几天,还请原谅. 案例整体介绍 在我们开始正式的案例开发介绍之前,我们先看一下整体的案例demo介绍,明白案例是做什么的. 从上图中,我们可以看出,这个案例主要是通过爬虫程序去采集纵横小说上的资源,然后将资源存储到自己的数据库中,将数据库中的需要检索的数据通过lucene建立索引文件,最后通过web服务展示数

基于lucene的案例开发:查询语句创建PackQuery

转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/44656141 http://www.llwjy.com/blogdetail/162e5e70516d7ddfb6df8f77e6b13a2b.html 个人博客站已经上线了,网址 www.llwjy.com~欢迎各位吐槽 ------------------------------------------------------------------------------

基于lucene的案例开发:Query查询

转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/42969443 在Lucene索引的搜索过程中,构建Query对象是一个十分重要的过程.对于Query的理解,可以把它想象成数据库SQL查询语句中的where条件(当然Query的功能要比sql强大很多),在这篇博客中,我们将重点介绍几种常用的Query子类:QueryParser. MultiFieldQueryParser.TermQuery .PrefixQuery. Ph

基于lucene的案例开发:IndexSearcher中检索方法

转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/43052829 前面我们介绍了Analyzer和Query,这篇我们就开始该系列最后一个类IndexSearcher的搜索API介绍,Lucene中重点API不止这里介绍的这一点,还有IndexWriter.Field.Highlighter等,这些就不在这一部分做介绍了,如若案例中用到的话,再做简单介绍. 查看Lucene4.3.1中IndexSearcher的API请点击这里