hdfs的FileSystem实例化

前言

在spark中经过hdfs的java接口并发写文件出现了数据丢失的问题,一顿操做后发现原来是FileSystem的缓存机制。补一课先java

 

FileSystem实例化

FileSystem.get(config)是如何建立一个hadoop的FileSystem。
分为3个步骤。
1.  初始化全部支持的FileSystem(没有实例话,只是缓存类)
2.  经过uri的scheme拿到相应FileSystem
3.  缓存机制(若是不关闭的话,默认是开启)
 
下面详细分析一下各步骤流程
1.   初始化
经过java提供的ServiceLoader来录入全部可能的FileSystem,就像这样
ServiceLoader<FileSystem> serviceLoader = ServiceLoader.load(FileSystem.class);
for (FileSystem fs : serviceLoader) {
  SERVICE_FILE_SYSTEMS.put(fs.getScheme(), fs.getClass());
}

 

待初始化的类经过配置文件声明,配置能够在hadoop-hdfs.jar里找到

捎带一嘴,java提供的ServiceLoader有点像乞丐版spring的依赖反转。spring

2.scheme
经过对Uri的解析来判断建立一个什么FileSystem,
例如
hdfs://master:9200/test的scheme就是hdfs。

而后经过scheme和已经缓存好的FileSystem映射,找到须要实例化的类。缓存

例如scheme是hdfs,那么就会建立一个DistributedFileSystem。

3. 缓存

FileSystem类中有一个Cache内部类,用于缓存已经被实例化的FileSystem。注意这个跟链接池仍是有区别的,Cache中的缓存只是一个map,能够被多个线程拿到。这就会有一个问题,当你多线程同时get FileSystem的时候,可能返回的是同一个对象。因此切记,在多线程场景中,不要随意调用FileSystem.close,你关的链接可能会影响到其余正在使用的线程。多线程

注意: 当你在其余框架上拿fileSystem对象须要额外注意,例如在spark上进行 FileSystem.get(),若是你想自定义某些配置,设置hdfs的副本数(dfs.replication) 之类,你必须在configuration中关闭FileSystem的缓存机制,也就是设置并发

configuration.set("fs.hdfs.impl.disable.cache","true")

这很重要,由于你不肯定spark是否在你以前建立了一个FileSystem,而你获得的可能不是你想要的。框架

 

参考资料oop

// 遇到的相同问题spa

https://www.darkal.cn/2017/03/filesystem-get%E4%BB%8E%E7%BC%93%E5%AD%98cache%E4%B8%AD%E8%8E%B7%E5%BE%97%E8%BF%9E%E6%8E%A5%E5%AF%BC%E8%87%B4%E7%9A%84%E9%97%AE%E9%A2%98/线程

相关文章
相关标签/搜索