- 浏览: 1055605 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (1441)
- 软件思想&演讲 (9)
- 行业常识 (250)
- 时时疑问 (5)
- java/guava/python/php/ruby/R/scala/groovy (213)
- struct/spring/springmvc (37)
- mybatis/hibernate/JPA (10)
- mysql/oracle/sqlserver/db2/mongdb/redis/neo4j/GreenPlum/Teradata/hsqldb/Derby/sakila (268)
- js/jquery/jqueryUi/jqueryEaseyUI/extjs/angulrJs/react/es6/grunt/zepto/raphael (81)
- ZMQ/RabbitMQ/ActiveMQ/JMS/kafka (17)
- lucene/solr/nuth/elasticsearch/MG4J (167)
- html/css/ionic/nodejs/bootstrap (19)
- Linux/shell/centos (56)
- cvs/svn/git/sourceTree/gradle/ant/maven/mantis/docker/Kubernetes (26)
- sonatype nexus (1)
- tomcat/jetty/netty/jboss (9)
- 工具 (17)
- ETL/SPASS/MATLAB/RapidMiner/weka/kettle/DataX/Kylin (11)
- hadoop/spark/Hbase/Hive/pig/Zookeeper/HAWQ/cloudera/Impala/Oozie (190)
- ios/swift/android (9)
- 机器学习&算法&大数据 (18)
- Mesos是Apache下的开源分布式资源管理框架 (1)
- echarts/d3/highCharts/tableau (1)
- 行业技能图谱 (1)
- 大数据可视化 (2)
- tornado/ansible/twisted (2)
- Nagios/Cacti/Zabbix (0)
- eclipse/intellijIDEA/webstorm (5)
- cvs/svn/git/sourceTree/gradle/jira/bitbucket (4)
- jsp/jsf/flex/ZKoss (0)
- 测试技术 (2)
- splunk/flunm (2)
- 高并发/大数据量 (1)
- freemarker/vector/thymeleaf (1)
- docker/Kubernetes (2)
- dubbo/ESB/dubboX/wso2 (2)
最新评论
介绍了lucene的存储根基Directory的一些原理,以及也给出了Directory家族的继承分布图,那么本篇呢,将重点介绍下Directory的一个很重要的子类FSDirectory,为什么说此类非常重要呢?如果你是正在使用lucene的开发者,那么你就知道,我们经常使用的一行代码:
Java代码 复制代码 收藏代码
1.Directory directory=FSDirectory.open(new File(indexPath))
通过这行代码,我们可以获取一个Directory的子类文件存储目录,然后我们对索引的一些操作,都是以这个子类的文件目录为基础的,
下面我们从源码的角度来详细剖析下FSDirectory这个类的作用,在此之前,散仙先用一个表格来介绍下lucene存储索引的几种方式:
序号 方式
1 将索引存储在内存中
2 将索引通过JDBC存储在数据库中
3 将索引存储在一般的文件系统上,如Windows,Linux,Solaris
4 将索引存储在分布式文件系统上,如HDFS
上面的几种存储方式是lucene目前为止,能够支持良好的的格式,那么今天,散仙要介绍的FSDirectory这类方式,就是上图表格中,第三类基于文件系统存储方式的根基,FSDirectory并不是一个具体的文件目录,通常情况下,我们使用的是FSDirectory下某一个具体的子类(MMapDirectory,SimpleFSDirectory,NIOFSDirectory)来作为我们的索引目录,那么我们可能有个很大的疑惑,我们在实际开发中大部分时候并没有直接指定具体使用的是那个目录,为什么我们还能正常使用它呢?
别着急,下面散仙,会给大家详细解说的,我们先来看下我们经常使用的那个FSDirectory的open()方法源码是怎么实现的:
Java代码 复制代码 收藏代码
1./** Just like {@link #open(File)}, but allows you to
2. * also specify a custom {@link LockFactory}. */
3. public static FSDirectory open(File path, LockFactory lockFactory) throws IOException {
4. if ((Constants.WINDOWS || Constants.SUN_OS || Constants.LINUX)
5. && Constants.JRE_IS_64BIT && MMapDirectory.UNMAP_SUPPORTED) {
6. return new MMapDirectory(path, lockFactory);
7. } else if (Constants.WINDOWS) {
8. return new SimpleFSDirectory(path, lockFactory);
9. } else {
10. return new NIOFSDirectory(path, lockFactory);
11. }
12. }
这段代码,还是比较通俗易懂的,相信各位朋友,已经看出来它是怎么实现的,那么散仙就来分析一下这段代码的含义,事实上我们通过open方法,lucene底层通常情况下,会给我们选择一个最适合我们当前操作系统用的索引目录,当然这种选择通常跟我们的JRE的位数是直接相关的,大多数的Solaris,Linux和windows64位系统的jre会返回MMapDirectory,而其他的一些位数的JRE,如32位的JRE在Windows上会返回SimpleFSDirectory,剩余的部分则会直接使用NIOFSDirectory来存储索引。那么这三种方式有什么不同呢?散仙总结如下:
1,SimpleFSDirectory,这个类简单的实现使用RandomAccessFile来完成索引的存储,读写速度一般,并发性很差,在多个线程同时访问索引时,会造成线程同步,从而大大降低了性能,当然,如果我们并发性不是很大的话,使用它也是一个不错的选择
2,MMapDirectory使用内存映射IO的方式来操作索引,在性能上是非常优秀的,读写速度非常快,并发性支持一般,当然这种情况仅仅局限于,你的索引的大小小于系统内存的时候,这才是一个好的选择,否则,使用不当,将常常会造成内存溢出的异常。
3,NIOFSDirectory使用的是JAVA NIO的 FileChannel的来操作索引的,读写速度快,对并发支持非常优秀,因为它利用NIO的特性,避免了同步的读取,所以在高并发的场景下,这个目录往往是最佳的选择。
下面,我们来分析下FSDirectory的另外一个重要的方法sysc()。
Java代码 复制代码 收藏代码
1. protected final Set<String> staleFiles = synchronizedSet(new HashSet<String>()); // Files written, but not yet sync'ed
2.
3. @Override
4. public void sync(Collection<String> names) throws IOException {
5. ensureOpen();
6. Set<String> toSync = new HashSet<String>(names);//需要持久化的一些元数据标识
7. toSync.retainAll(staleFiles);//此方法会与staleFiles里面的数据求交集
8.
9. for (String name : toSync)
10. fsync(name);//把内存中或缓冲区的数据,强制写到磁盘上,确保数据不会流失
11.
12. staleFiles.removeAll(toSync);//在staleFiles中移除已经持久化到磁盘的数据,等待下一次的数据添加
13. }
14.
15.protected void fsync(String name) throws IOException {
16. File fullFile = new File(directory, name);
17. boolean success = false;
18. int retryCount = 0;
19. IOException exc = null;
20. while (!success && retryCount < 5) {
21. retryCount++;
22. RandomAccessFile file = null;
23. try {
24. try {
25. file = new RandomAccessFile(fullFile, "rw");
26. file.getFD().sync();//写入磁盘上
27. success = true;
28. } finally {
29. if (file != null)
30. file.close();
31. }
32. } catch (IOException ioe) {
33. if (exc == null)
34. exc = ioe;
35. try {
36. // Pause 5 msec
37. Thread.sleep(5);
38. } catch (InterruptedException ie) {
39. throw new ThreadInterruptedException(ie);
40. }
41. }
42. }
43. if (!success)
44. // Throw original exception
45. throw exc;
46. }
其实,sysc这个方法,是从Directory这个顶级父类,继承过来的,由FSDirectory这个类,对其进行了重写,这个方法的目的,就是定期根据某些条件,来将我们内存或缓冲区的数据持久化到磁盘上,以确保我们已经索引的数据是非常安全的,不会因为一些意外情况,如系统崩溃,或突然宕机,停电的情况下,对索引结构造成破坏或一些影响。
一个简单的工作流程是这样的,当我们进行添加操作时,文件目录通常会打开一个或几个特定的文件格式来存储我们的数据,比如索引正文的存储,向量的存储,位置增量的存储,不同的索引格式负责存储不同的内容,当一些数据添加完毕后,通过某些条件触发持久化操作,比如超出了设置的缓冲区大小,或者超出了默认的Doc数,或者我们调用了commit方法,这时lucene会调用sysc方法,来把已经添加的数据,存储到磁盘上,以确保数据的安全存储,当然这些工作,lucene底层已经给我们实现好了,我们并不需要显示的调用这个方法来完成数据持久操作,就能绝大多数情况下,安全可靠的完成存储,而这一切正是sysc发挥的关键作用。
Java代码 复制代码 收藏代码
1.Directory directory=FSDirectory.open(new File(indexPath))
通过这行代码,我们可以获取一个Directory的子类文件存储目录,然后我们对索引的一些操作,都是以这个子类的文件目录为基础的,
下面我们从源码的角度来详细剖析下FSDirectory这个类的作用,在此之前,散仙先用一个表格来介绍下lucene存储索引的几种方式:
序号 方式
1 将索引存储在内存中
2 将索引通过JDBC存储在数据库中
3 将索引存储在一般的文件系统上,如Windows,Linux,Solaris
4 将索引存储在分布式文件系统上,如HDFS
上面的几种存储方式是lucene目前为止,能够支持良好的的格式,那么今天,散仙要介绍的FSDirectory这类方式,就是上图表格中,第三类基于文件系统存储方式的根基,FSDirectory并不是一个具体的文件目录,通常情况下,我们使用的是FSDirectory下某一个具体的子类(MMapDirectory,SimpleFSDirectory,NIOFSDirectory)来作为我们的索引目录,那么我们可能有个很大的疑惑,我们在实际开发中大部分时候并没有直接指定具体使用的是那个目录,为什么我们还能正常使用它呢?
别着急,下面散仙,会给大家详细解说的,我们先来看下我们经常使用的那个FSDirectory的open()方法源码是怎么实现的:
Java代码 复制代码 收藏代码
1./** Just like {@link #open(File)}, but allows you to
2. * also specify a custom {@link LockFactory}. */
3. public static FSDirectory open(File path, LockFactory lockFactory) throws IOException {
4. if ((Constants.WINDOWS || Constants.SUN_OS || Constants.LINUX)
5. && Constants.JRE_IS_64BIT && MMapDirectory.UNMAP_SUPPORTED) {
6. return new MMapDirectory(path, lockFactory);
7. } else if (Constants.WINDOWS) {
8. return new SimpleFSDirectory(path, lockFactory);
9. } else {
10. return new NIOFSDirectory(path, lockFactory);
11. }
12. }
这段代码,还是比较通俗易懂的,相信各位朋友,已经看出来它是怎么实现的,那么散仙就来分析一下这段代码的含义,事实上我们通过open方法,lucene底层通常情况下,会给我们选择一个最适合我们当前操作系统用的索引目录,当然这种选择通常跟我们的JRE的位数是直接相关的,大多数的Solaris,Linux和windows64位系统的jre会返回MMapDirectory,而其他的一些位数的JRE,如32位的JRE在Windows上会返回SimpleFSDirectory,剩余的部分则会直接使用NIOFSDirectory来存储索引。那么这三种方式有什么不同呢?散仙总结如下:
1,SimpleFSDirectory,这个类简单的实现使用RandomAccessFile来完成索引的存储,读写速度一般,并发性很差,在多个线程同时访问索引时,会造成线程同步,从而大大降低了性能,当然,如果我们并发性不是很大的话,使用它也是一个不错的选择
2,MMapDirectory使用内存映射IO的方式来操作索引,在性能上是非常优秀的,读写速度非常快,并发性支持一般,当然这种情况仅仅局限于,你的索引的大小小于系统内存的时候,这才是一个好的选择,否则,使用不当,将常常会造成内存溢出的异常。
3,NIOFSDirectory使用的是JAVA NIO的 FileChannel的来操作索引的,读写速度快,对并发支持非常优秀,因为它利用NIO的特性,避免了同步的读取,所以在高并发的场景下,这个目录往往是最佳的选择。
下面,我们来分析下FSDirectory的另外一个重要的方法sysc()。
Java代码 复制代码 收藏代码
1. protected final Set<String> staleFiles = synchronizedSet(new HashSet<String>()); // Files written, but not yet sync'ed
2.
3. @Override
4. public void sync(Collection<String> names) throws IOException {
5. ensureOpen();
6. Set<String> toSync = new HashSet<String>(names);//需要持久化的一些元数据标识
7. toSync.retainAll(staleFiles);//此方法会与staleFiles里面的数据求交集
8.
9. for (String name : toSync)
10. fsync(name);//把内存中或缓冲区的数据,强制写到磁盘上,确保数据不会流失
11.
12. staleFiles.removeAll(toSync);//在staleFiles中移除已经持久化到磁盘的数据,等待下一次的数据添加
13. }
14.
15.protected void fsync(String name) throws IOException {
16. File fullFile = new File(directory, name);
17. boolean success = false;
18. int retryCount = 0;
19. IOException exc = null;
20. while (!success && retryCount < 5) {
21. retryCount++;
22. RandomAccessFile file = null;
23. try {
24. try {
25. file = new RandomAccessFile(fullFile, "rw");
26. file.getFD().sync();//写入磁盘上
27. success = true;
28. } finally {
29. if (file != null)
30. file.close();
31. }
32. } catch (IOException ioe) {
33. if (exc == null)
34. exc = ioe;
35. try {
36. // Pause 5 msec
37. Thread.sleep(5);
38. } catch (InterruptedException ie) {
39. throw new ThreadInterruptedException(ie);
40. }
41. }
42. }
43. if (!success)
44. // Throw original exception
45. throw exc;
46. }
其实,sysc这个方法,是从Directory这个顶级父类,继承过来的,由FSDirectory这个类,对其进行了重写,这个方法的目的,就是定期根据某些条件,来将我们内存或缓冲区的数据持久化到磁盘上,以确保我们已经索引的数据是非常安全的,不会因为一些意外情况,如系统崩溃,或突然宕机,停电的情况下,对索引结构造成破坏或一些影响。
一个简单的工作流程是这样的,当我们进行添加操作时,文件目录通常会打开一个或几个特定的文件格式来存储我们的数据,比如索引正文的存储,向量的存储,位置增量的存储,不同的索引格式负责存储不同的内容,当一些数据添加完毕后,通过某些条件触发持久化操作,比如超出了设置的缓冲区大小,或者超出了默认的Doc数,或者我们调用了commit方法,这时lucene会调用sysc方法,来把已经添加的数据,存储到磁盘上,以确保数据的安全存储,当然这些工作,lucene底层已经给我们实现好了,我们并不需要显示的调用这个方法来完成数据持久操作,就能绝大多数情况下,安全可靠的完成存储,而这一切正是sysc发挥的关键作用。
发表评论
-
elasticsearch异常信息汇总
2017-11-06 09:34 15471.IndexMissingException 异常信息 ... -
Elasticsearch的架构
2018-03-22 10:30 511为什么要学习架构? Elasticsearch的一些架构 ... -
怎么在Ubuntu上打开端口
2017-10-21 20:45 0Netstat -tln 命令是用来查看linux的端口使用情 ... -
Elasticsearch工作原理
2018-03-22 10:30 451一、关于搜索引擎 各 ... -
Elasticsearch的路由(Routing)特性
2017-10-11 10:41 0Elasticsearch路由机制介 ... -
Elasticsearch中的segment理解
2017-10-11 09:58 1893在Elasticsearch中, 需要搞清楚几个名词,如se ... -
Elasticsearch的路由(Routing)特性
2017-09-28 16:52 618Elasticsearch路由机制介绍 Elastics ... -
Elasticsearch 的 Shard 和 Segment
2017-09-28 16:05 1201Shard(分片) 一个Shard就是一个Lu ... -
开源大数据查询分析引擎现状
2017-09-22 03:04 832大数据查询分析是云计算中核心问题之一,自从Google在20 ... -
大数据处理方面的 7 个开源搜索引擎
2017-09-22 03:01 496大数据是一个包括一切 ... -
开源大数据查询分析引擎现状
2017-09-23 11:26 551大数据查询分析是云计算中核心问题之一,自从Google在2 ... -
elasticsearch 把很多类型都放在一个索引下面 会不会导致查询慢
2017-09-25 09:45 984主要看数据量ES索引优 ... -
腾讯大数据Hermes爱马仕的系统
2017-09-23 11:15 996腾讯大数据最近做了几件事,上线了一个官方网站http:// ... -
配置高性能Elasticsearch集群的9个小贴士
2017-09-25 10:02 593Loggly服务底层的很多 ... -
Elasticsearch与Solr
2017-09-25 16:24 554Elasticsearch简介* Elasti ... -
大数据杂谈微课堂|Elasticsearch 5.0新版本的特性与改进
2017-09-26 09:57 808Elastic将在今年秋季的 ... -
ElasticSearch性能优化策略
2017-09-26 09:51 450ElasticSearch性能优化主 ... -
ES索引优化
2017-09-19 20:39 0ES索引优化篇主要从两个方面解决问题,一是索引数据过程;二是 ... -
分词与索引的关系
2017-09-19 20:33 0分词与索引,是中文搜索里最重要的两个技术,而且两者间是密不可 ... -
Elasticsearch中的segment理解
2017-09-19 20:30 0在Elasticsearch中, 需要搞清楚几个名词,如se ...
相关推荐
FSDirectory fsdir = new FSDirectory(); ``` 这里分别创建了一个基于内存的`RAMDirectory`和基于文件系统的`FSDirectory`对象。 2. **创建IndexWriter实例**: ```java IndexWriter ramWriter = new ...
FSDirectory directory = FSDirectory.getDirectory(indexDir,false); IndexSearcher searcher = new IndexSearcher(directory); // 检查索引是否存在 if(!indexDir.exists()){ System.out.println("The ...
### Hadoop源代码分析——FSDirectory深入解析 #### 一、引言 在深入了解Hadoop内部机制的过程中,源代码的分析是不可或缺的一环。本文将聚焦于Hadoop中的`FSDirectory`类,它是HDFS(Hadoop分布式文件系统)核心...
这个操作首先通过调用`FSNamesystem`的`renameTo`方法开始,接着由`renameToInternal`处理,最终由`FSDirectory`的`renameTo`实现。如果操作成功,还会更新文件的租约名称,确保数据的一致性。 2. 文件删除: `...
具体步骤包括获取两个或多个目录对象,如通过`FSDirectory.getDirectory()`方法指定索引路径;然后创建`ParallelReader`实例,并通过`add()`方法添加每个目录对应的`IndexReader`实例。最后,基于`ParallelReader`...
FSDirectory directory = FSDirectory.open(Paths.get("index")); // 创建分析器 Analyzer analyzer = new StandardAnalyzer(); // 创建 IndexWriter 配置并打开 IndexWriter IndexWriterConfig config = new...
1.1. `FSDirectory.GetDirectory(path, false)`:这个方法创建一个指向索引文件的`FSDirectory`实例,`create`参数决定是否创建新目录。 1.1.1. `GetDirectory(new System.IO.FileInfo(path), create)`:这是获取...
1. 使用合适的数据结构:例如,使用`FSDirectory`存储索引,而非内存中的`RAMDirectory`。 2. 分片和分布式搜索:对于大型数据集,可以将索引分成多个分片,并在多台机器上分布式存储和搜索。 3. 倒排索引:这是...
Lucene支持两种存储方式:内存索引(RAMDirectory)和磁盘索引(如FSDirectory)。内存索引适用于临时或测试环境,而磁盘索引适合大规模数据持久化存储。`Directory`类及其子类封装了对索引文件的读写操作。 6. **...
- 在生产环境中,通常会使用 `FSDirectory` 而不是 `RAMDirectory`,因为后者只适合测试,不适合大型或持久化的索引。 通过以上步骤,你可以了解如何使用 Lucene.NET 创建和搜索简单的文本索引。在实际应用中,...
在`src/java/org/apache/lucene/search`目录中,`Query`类及其子类定义了各种查询类型,如`TermQuery`、`BooleanQuery`和`WildcardQuery`。查询构造器如`QueryParser`将用户的自然语言输入转换为对应的查询对象,...
a) 文件系统:FSDirectory: FSDirectory.open(File file); b) 内存RAMDirectory: new RAMDirectory(); 3) Analyzer: 分词器。 a) StandardAnalyzer: 标准分词器。对英文采用空白, 标点符号进行分词。对中文采用...
1. **创建一个Directory对象**:这是Lucene用来存储索引的接口,可以是内存中的RAMDirectory,也可以是磁盘上的FSDirectory。 2. **创建Analyzer**:Analyzer负责将文本分词,如英文单词。这里我们可以使用...
IndexSearcher searcher = new IndexSearcher(FSDirectory.Open(new System.IO.DirectoryInfo(IndexPath)), true); // 获取文档总数 int count = searcher.MaxDoc(); // 创建文档并添加到索引中 Document doc = new...
FSDirectory directory = FSDirectory.open(Paths.get("indexdir")); ``` 2. **配置Analyzer** Lucene对中文处理需要特殊的Analyzer,如`IKAnalyzer`或`SmartChineseAnalyzer`。这些Analyzer能对中文进行分词,...
- **Directory**: 存储索引的抽象接口,如FSDirectory用于在文件系统中存储,RAMDirectory则将索引存储在内存中。 - **Document**: 表示一个待索引的文档,可以包含多个Field(字段),每个Field都有特定的类型,...
- Directory类:定义了索引文件的存储结构,提供了FSDirectory(磁盘存储)、RAMDirectory(内存存储)和MmapDirectory(内存映射)等不同类型的实现。 7. **Util**: - 公共工具类,包含时间转换、字符串处理等...
5. **存储模块**:`Directory`接口和它的实现类(如`FSDirectory`、`RAMDirectory`)负责索引和文档数据的存储。`FSDirectory`使用文件系统,而`RAMDirectory`则在内存中存储,适用于测试环境。 6. **评分模块**:...
Directory directory = FSDirectory.open(indexLocation.toPath()); ``` ### 3. 分析器设置 分析器用于对输入的文本进行分词。Lucene提供了多种分析器,如`StandardAnalyzer`,适用于英文文本;对于中文,通常使用...