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

释放双眼,带上耳机,听听看~!

转载请注明出处:http://www.voidcn.com/article/p-ncmolctp-bkz.html

http://www.llwjy.com/blogdetail/63d4c488a2cccb5851c0498d374951c9.html

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

基本原理

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

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

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

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

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

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

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

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

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

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

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

配置类

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

ConfigBean

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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
1/**  
2 *@Description:  索引基础配置属性
3 */
4package com.lulei.lucene.index.model;
5
6import org.apache.lucene.analysis.Analyzer;
7import org.apache.lucene.analysis.standard.StandardAnalyzer;
8import org.apache.lucene.util.Version;
9
10public 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}
70
71

1
2

2

IndexConfig

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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
1 /**  
2 *@Description: 索引的相关配置参数
3 */
4package com.lulei.lucene.index.model;  
5
6import java.util.HashSet;
7
8public 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}
33
34

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

给TA打赏
共{{data.count}}人
人已打赏
安全运维

OpenSSH-8.7p1离线升级修复安全漏洞

2021-10-23 10:13:25

安全运维

设计模式的设计原则

2021-12-12 17:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索