1. 程式人生 > >基於lucene的案例開發:實現實時索引基本原理

基於lucene的案例開發:實現實時索引基本原理

      個人的部落格小站也搭建成功,網址:www.llwjy.com ,歡迎大家來吐槽~

基本原理

      在前面的部落格中也說過,程式初始話索引檔案是十分消耗系統資源的,因此要想實現實時索引就不能實時的去修改索引檔案、重新載入索引檔案,就必須考慮如何使用記憶體來實現這實時索引;在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/

相關推薦

基於lucene案例開發實現實時索引基本原理

      個人的部落格小站也搭建成功,網址:www.llwjy.com ,歡迎大家來吐槽~ 基本原理       在前面的部落格中也說過,程式初始話索引檔案是十分消耗系統資源的,因此要想實現實時索引就不能實時的去修改索引檔案、重新載入索引檔案,就必須考慮如何使用記憶

基於lucene案例開發建立索引

      從這篇部落格開始,不論是API介紹還是後面的案例開發,都是基於 lucene4.3.1 這個版本,Lucene4.3.1 下載請點選這裡, Lucene其他版本下載請點選這裡,Lucene4.3.1官方API文件請點選這裡。 建立索引demo       在

基於lucene案例開發IndexSearcher中檢索方法

轉載請註明出處:http://blog.csdn.net/xiaojimanman/article/details/43052829       前面我們介紹了Analyzer和Query,這篇我們就開始該系列最後一個類IndexSearcher的搜尋API介紹,Lucen

基於lucene案例開發分詞器介紹

      在lucene建立索引的過程中,資料資訊的處理是一個十分重要的過程,在這一過程中,主要的部分就是這一篇部落格的主題:分詞器。在下面簡單的demo中,介紹了7中比較常見的分詞技術,即:CJKAnalyzer、KeywordAnalyzer、SimpleAnaly

基於gin的golang web開發實現使用者登入

前文分別介紹過了[Resty][1]和[gin-jwt][2]兩個包,```Resty```是一個HTTP和REST客戶端,```gin-jwt```是一個實現了JWT的Gin中介軟體。本文將使用這兩個包來實現一個簡單的使用者登入功能。 ### 環境準備 實現登入功能之前要提前準備一個用於查詢使用者是否存

基於Jquery插件Uploadify實現實時顯示進度條上傳圖片

準備 深入學習 pla 回調 true bar put and 分割 網址:http://www.jb51.net/article/83811.htm 這篇文章主要介紹了基於Jquery插件Uploadify實現實時顯示進度條上傳圖片的相關資料,感興趣的小夥伴們可

[.NET] 簡單接入微信公眾號開發實現自動回復

ring echo AC tin 處理過程 文本消息 n) () token 簡單接入微信公眾號開發:實現自動回復 一、前提   先申請微信公眾號的授權,找到或配置幾個關鍵的信息(開發者ID、開發者密碼、IP白名單、令牌和消息加解密密鑰等)。 二、基本配置信

JQuery案例實現表格隔行換色

body ble () ++ doc cti seo head 姓名 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <t

JQuery案例實現全選、全不選和反選

lap lsp enter scrip ttr on() class cells span <!DOCTYPE html> <html> <head> <meta charset="UTF-8">

案例實現1+2+3+...+100的求和計算

color 圖片 author sum png main col 求和 bsp package project_06; /** * 2018年9月7日22:45:05 * @author Suaron XiaMen * */ public class Summa

音樂網站開發實現點選按鈕切換頁面背景圖的功能

        最近這一星期在做一個簡單小型的音樂播放器網站,目前各種功能基本都已經實現,包括切換上一曲下一曲,播放與暫停,隨機播放單曲迴圈順序播放模式切換,一首播放完畢自動按模式切換至下一曲,載入單句歌詞及所有歌詞等功能。另外就是本篇部落格要介紹的功能了,點

基於Lucene 7.1.0 實現搜尋引擎

引入lucene 7.1.0 所使用的jar包 <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-core</artifactId>

Modbus協議棧開發筆記之一實現功能的基本設計

Modbus作為開放式的工業通訊協議,在各種工業裝置中應用極其廣泛。本人也使用Modbus通訊很多年了,或者用現成的,或者針對具體應用開發,一直以來都想要開發一個比較通用的協議棧能在後續的專案中複用,而不必每次都寫一遍。現在利用專案研發的機會,開發一個自己的Modbus協議棧。 Modbus

Android開發實現分享給微信好友以及出現閃退的問題

轉載煩請註明本文出處~ 1.申請微信APPID      要實現分享到微信的功能,首先要到微信開放平臺申請一個APPID。但在申請APPID的時候需要填寫一個應用簽名和應用包名。需要注意的是包名必須與開發應用時的包名一致,應用簽名也必須去掉冒號而且字母為小寫。 2.應

Android開發實現系統自帶截圖功能 需要獲取System許可權

在一個service介面上,點選一個button按鈕,可以截圖 貼上程式碼: mButton.setOnClickListener(new OnClickListener(){          public void onClick(View arg0) {       

基於 Flume+Kafka+Spark Streaming 實現實時監控輸出日誌的報警系統

運用場景:我們機器上每天或者定期都要跑很多工,很多時候任務出現錯誤不能及時發現,導致發現的時候任務已經掛了很久了。  解決方法:基於 Flume+Kafka+Spark Streaming 的框架對這些任務的輸出日誌進行實時監控,當檢測到日誌出現Error的資訊就傳送郵件給

Android二維碼掃描開發實現思路與原理

現在二維碼已經非常普及了,那麼二維碼的掃描與處理也成為了Android開發中的一個必要技能。網上有很多關於Android中二維碼處理的帖子,大都是在講開源框架zxing用法,然後貼貼程式碼就完了,並沒有一個系統的分析和原理解析。其中涉及到的Camera的操作和YUV影

iOS開發實現圖片的打碼效果

    馬賽克(mosaic)作為人類進步路上的一大絆腳石,被人們所深惡痛絕。作為阻止人類進步小能手,我今天就給大家普及一下關於如何在iOS平臺實現圖片打碼效果的。 圖1、效果圖 本文主要介紹的是使用iOS平臺自身的API去實現圖片打碼效果的,沒有使用openCV。

Android 開發Paint畫筆的基本使用方法

1.setStyle(Paint.Style style)  設定畫筆樣式,取值有 Paint.Style.FILL :填充內部 Paint.Style.FILL_AND_STROKE :填充內部和描邊 Paint.Style.STROKE :僅描邊、 注意STROKE、F

Lucene學習總結之一全文檢索的基本原理

一、總論 Lucene是一個高效的,基於Java的全文檢索庫。 所以在瞭解Lucene之前要費一番工夫瞭解一下全文檢索。 那麼什麼叫做全文檢索呢?這要從我們生活中的資料說起。 我們生活中的資料總體分為兩種:結構化資料和非結構化資料。 結構化資料:指具