轉載請注明出處:[http://blog.csdn.net/xiaojimanman/article/details/43982653](http://blog.csdn.net/xiaojimanman/article/details/43982653)
[http://www.llwjy.com/blogdetail/63d4c488a2cccb5851c0498d374951c9.html](http://www.llwjy.com/blogdetail/63d4c488a2cccb5851c0498d374951c9.html)
個人的博客小站也搭建成功,網址:[www.llwjy.com?](http://www.llwjy.com),歡迎大家來吐槽~
**基本原理**
在前面的博客中也說過,程序初始話索引文件是十分消耗系統資源的,因此要想實現實時索引就不能實時的去修改索引文件、重新加載索引文件,就必須考慮如何使用內存來實現這實時索引;在Lucene4.3.1版本(之前的版本也有,但是在后面的版本中就將NRT*相關的類刪除了)中NRT*相關類就提供了創建實時索引(偽實時索引)的相關方法,將IndexWrite的相關操作委托給TrackingIndexWriter來處理,實現了內存索引和硬盤索引的結合,通過NRTManager為外部提供可用的索引,當然,在執行commit(之前[創建索引](http://blog.csdn.net/xiaojimanman/article/details/42872711)中有相關介紹)操作之前,操作的數據都是存在內存中,一旦宕機或者服務重,這些數據都將丟失,因此就需要自己添加一個守護線程去不斷的執行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://blog.csdn.net/xiaojimanman/article/category/2841877)。或訪問網址http://blog.csdn.net/xiaojimanman/article/category/2841877 或?[http://www.llwjy.com/](http://www.llwjy.com)
- 前言
- 寫在開始之前
- lucene初始認知
- 索引數學模型
- 索引文件結構
- 創建索引
- 搜索索引
- 分詞器介紹
- Query查詢
- IndexSearcher中檢索方法
- 更新說明
- 案例初識
- JsonUtil &amp; XmlUtil
- 基ClassUtil &amp; CharsetUtil
- ParseUtil &amp; ParseRequest
- 數據庫連接池
- 實現實時索引基本原理
- 實時索引管理類IndexManager
- 實時索引的檢索
- 實時索引的修改
- 查詢語句創建PackQuery
- 縱橫小說更新列表頁抓取
- 縱橫小說簡介頁采集
- 縱橫小說章節列表采集
- 縱橫小說閱讀頁采集
- 縱橫小說數據庫設計
- 縱橫小說數據庫操作
- 縱橫小說分布式采集