是否可以在一台计算机上使用HDFS客户端从HDSF集群实现分布式读取?
我用一个由3个数据节点(DN1,DN2,DN3)组成的集群进行了实验.然后我从位于DN1的客户端程序中的10个独立文件中同时读取10个,并且它似乎只是从DN1读取数据.其他数据节点(DN2,DN3)显示零活动(从调试日志判断).
我已检查所有文件的块是否在所有3个数据节点上复制,因此如果我关闭DN1,则从DN2读取数据(仅限DN2).
增加读取的数据量没有帮助(尝试从2GB到30GB).
由于我需要读取多个大文件并从中提取少量数据(少量Kb),我想避免使用map/reduce,因为它需要设置更多服务并且还需要编写每个分割的输出任务回到HDFS.相反,将结果从数据节点直接返回到我的客户端程序会很好.
我用SequenceFile
这种方式读取/写入数据(jdk7):
//Run in thread pool on multiple files simultaneously
List result = new ArrayList<>();
LongWritable key = new LongWritable();
Text value = new Text();
try(SequenceFile.Reader reader = new SequenceFile.Reader(conf,
SequenceFile.Reader.file(filePath)){
reader.next(key);
if(key.get() == ID_I_AM_LOOKING_FOR){
reader.getCurrentValue(value);
result.add(value.toString());
}
}
return result; //results from multiple workers are merged later
任何帮助赞赏.谢谢!
我担心你看到的行为是按设计的.从Hadoop文档:
副本选择
为了最大限度地减少全局带宽消耗和读取延迟,HDFS尝试满足最接近读取器的副本的读取请求.如果在与读取器节点相同的机架上存在副本,则该副本首选满足读取请求.如果angg/HDFS群集跨越多个数据中心,则驻留在本地数据中心的副本优先于任何远程副本.
可以通过相应的Hadoop源代码进一步确认:
LocatedBlocks getBlockLocations(...) {
LocatedBlocks blocks = getBlockLocations(src, offset, length, true, true);
if (blocks != null) {
//sort the blocks
DatanodeDescriptor client = host2DataNodeMap.getDatanodeByHost(
clientMachine);
for (LocatedBlock b : blocks.getLocatedBlocks()) {
clusterMap.pseudoSortByDistance(client, b.getLocations());
// Move decommissioned datanodes to the bottom
Arrays.sort(b.getLocations(), DFSUtil.DECOM_COMPARATOR);
}
}
return blocks;
}
即,所有可用的副本都是一个接一个地尝试,如果前者失败但最近的副本总是第一个.
另一方面,如果您通过HDFS代理访问HDFS文件,它会随机选择数据节点.但我不认为这就是你想要的.