您的位置:首页 > 其它

FileSwitchDirectory 学习笔记 并在solr上的使用

2012-09-21 23:43 639 查看
FileSwitchDirectory实现原理与应用

FileSwitchDirectory是lucene的另一种Directory实现类,从名字个就可以理解为文件切换的Directory实现,

的确是针对lucene的不同的索引文件使用不同的Directory .借助FileSwitchDirectory整合不同的Directory实现类的优点于一身。

比如MMapDirectory,借助内存映射文件方式提高性能,但又要减少内存切换的可能 ,当索引太大的时候,内存映射也需要不断地切换,这样优点也可能变缺点,而之前的NIOFSDirectory实现java NIO的方式提高高并发性能,但又因高并发也会导致IO过多的影响,所以这次可以借助FileSwitchDirectory发挥他们两的优点。

MMapDirectory与NIOFSDirectory的实现差别。

NIOFSDirectory----只是使用了直接内存读取文件缓存方式

@Override

protected void newBuffer(byte[] newBuffer) {

super.newBuffer(newBuffer);

byteBuf = ByteBuffer.wrap(newBuffer);

}

MMapDirectory------使用MMap技术映射文件,默认会映射1G的内存(64位)或者256m(32位系统))

MMapDiretory就是将文件映射到内存中。。使用的是MMap技术

this.buffers[bufNr] = rafc.map(MapMode.READ_ONLY, bufferStart, bufSize);

首先将索引目录里占比例比较小的文件使用MMapDirectory,这样几乎可以全部映射到内存里了。。而占有大比例的文档存储文件交由于NIOFSDirectory方式读取。

这个结合不错呀。。

FileSwitchDirectory实现代码解析

FileSwitchDirectory的代码很简单,因为可以理解为它就是一个Dao的入口也是个控制器,所以它并没有具体的文件操纵实现。

先了解它的构造是:

public FileSwitchDirectory(Set<String> primaryExtensions, Directory primaryDir, Directory secondaryDir, boolean doClose) {
    this.primaryExtensions = primaryExtensions;
    this.primaryDir = primaryDir;
    this.secondaryDir = secondaryDir;
    this.doClose = doClose;
    this.lockFactory = primaryDir.getLockFactory();
  }


首先是文件后缀的集合参数

主要的Directory

次要的Directory

是否关闭的时候调用

所以都是调用对应的Directory获得IndexInput 与IndexOuput

@Override
  public IndexInput openInput(String name) throws IOException {
    return getDirectory(name).openInput(name);
  }


@Override
  public IndexOutput createOutput(String name) throws IOException {
    return getDirectory(name).createOutput(name);
  }


通过文件名字取到对应的Directory

private Directory getDirectory(String name) {
    String ext = getExtension(name);
    if (primaryExtensions.contains(ext)) {
      return primaryDir;
    } else {
      return secondaryDir;
    }
  }


solr使用的DirectoryFactory实现

/**
 * 
 * 
 * 支持某些后缀文件不作映射优化,比如去掉fdt,fdx
 * 
 * 
 * 
 *   
 <directoryFactory class="solr.MMapDirectoryFactoryExt">
    <str name="unmap">true</str>
    <lst name="filetypes">
       <bool name="fdt">false</bool>
       <bool name="fdx">false</bool>
   </lst>
 </directoryFactory>
 *
 */
public class MMapDirectoryFactoryExt extends DirectoryFactory {
	// filetypes不作映射
	private Set<String> nonMappedFiles = new HashSet<String>();
	// 是否使用不映射选择
	private Boolean useUnmapHack = false;

	public Directory open(String path) throws IOException {
		MMapDirectory mmapDir = new MMapDirectory(new File(path));
		mmapDir.setUseUnmap(useUnmapHack);
		return new FileSwitchDirectory(nonMappedFiles, mmapDir, FSDirectory.open(new File(path)), true);
	}

	public void init(NamedList args) {
		Object unmap, namedlist;
		nonMappedFiles = new HashSet<String>();
		if ((unmap = args.get("unmap")) instanceof Boolean)
			useUnmapHack = (Boolean) unmap;
		if ((namedlist = args.get("filetypes")) instanceof NamedList) {
			NamedList filetypes = (NamedList) namedlist;
			for (String type : IndexFileNames.INDEX_EXTENSIONS) {
				Object mapped = filetypes.get(type);
				if (Boolean.FALSE.equals(mapped))
					nonMappedFiles.add(type);
			}
		}
	}
}


solrconfig.xml上的配置,使用于新的DirectoryFactory

<directoryFactory class="solr.MMapDirectoryFactory">
<str name="unmap">true</str>
<lst name="filetypes">
<bool name="fdt">false</bool>
<bool name="tii">false</bool>
</lst>
</directoryFactory>


线上的索引文件大小:

7.3G ./_y8b.fdt

201M ./_y8b.fdx

4.0K ./_y8b.fnm

1.8G ./_y8b.frq

76M ./_y8b.nrm

537M ./_y8b.prx

7.1M ./_y8b.tii

571M ./_y8b.tis

4.0K ./segments.gen

4.0K ./segments_1p

由于tii文件会加载到内存,所以这个不须要映射,fdt文件太大,主要是正向存储的数据,可以使用NiOFSDirectory方式

还有一个文件frq文件好大,这个也是需要考虑的。

public final void setMaxChunkSize(final int maxChunkSize) {
    if (maxChunkSize <= 0)
      throw new IllegalArgumentException("Maximum chunk size for mmap must be >0");
    //System.out.println("Requested chunk size: "+maxChunkSize);
    this.chunkSizePower = 31 - Integer.numberOfLeadingZeros(maxChunkSize);
    assert this.chunkSizePower >= 0 && this.chunkSizePower <= 30;
    //System.out.println("Got chunk size: "+getMaxChunkSize());
  }


从上面的代码可以看出,最大也只能是1G大小。。。杯具。。

转载请写明引用:FileSwitchDirectory 学习笔记 并在solr上的使用
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: