【问题标题】:short read on HDFSHDFS 上的短读
【发布时间】:2021-12-11 06:48:43
【问题描述】:

我有一个文件 (~.9GB),我正在尝试读取缓冲区大小为 1MiB 的文件,它会导致 65536 字节的短读取。

bash-4.2$ hadoop fs -ls /x/F1
-rw-r--r--   3 hdfs supergroup  996147200 2021-10-25 13:56 /x/F1
bash-4.2$

为了缩小范围,我在下面有一个简单的示例代码。

void readtest()
{

        hdfsFS fs = hdfsConnect("default", 0);
        const char* readPath = "/x/F1";
        hdfsFile readFile = hdfsOpenFile(fs, readPath, O_RDONLY |O_CREAT, 0, 0, 0);
        if(!readFile) {
          fprintf(stderr, "Failed to open %s for reading!\n", readPath);
          exit(-1);
        }
        char* buffer = malloc(1048576);
        int count  = hdfsRead(fs, readFile, (void*) buffer, 1048576);
        printf("\n count on read %d \n", count);
}

bash-4.2$ ./sample
count on read 65536
bash-4.2$ 

然后我使用了原生 blocksize api,blocksize 原来是 128MB ,但是 read 仍然返回 64K。

void readtest()
{

        hdfsFS fs = hdfsConnect("default", 0);
        const char* readPath = "/x/F1";
        hdfsFile readFile = hdfsOpenFile(fs, readPath, O_RDONLY |O_CREAT, 0, 0, 0);
        if(!readFile) {
          fprintf(stderr, "Failed to open %s for writing!\n", readPath);
          exit(-1);
        }
        int blocksize  = hdfsGetDefaultBlockSizeAtPath(fs, readPath);
        printf("\n blocksize %d \n", blocksize);
        char* buffer = malloc(blocksize);
        int count  = hdfsRead(fs, readFile, (void*) buffer, blocksize);
        printf("\n count on read %d \n", count);
}

bash-4.2$ ./sample
blocksize 134217728
count on read 65536
bash-4.2$

为什么会有这样的行为?请有任何建议。

【问题讨论】:

    标签: c hadoop hdfs


    【解决方案1】:

    HDFS 使用的典型(默认)块大小为 128 MB。因此,一个 HDFS 文件被分割成 128 MB 的块,如果可能,每个块将驻留在不同的 DataNode 上。

    如果要更改默认块大小,必须在hdfs-site.xml 中手动配置。所以更改NameNode配置文件设置HDFS块大小,并在$HADOOP_HOME/conf/hdfs-site.xml中添加或修改以下内容。使用字节数提供块大小。此更改不会更改 HDFS 中已经存在的文件的块大小。只有更改后复制的文件才会具有新的块大小。所以需要再次复制才能生效。

    <property> 
        <name>dfs.block.size<name> 
        <value>134217728<value> 
        <description>Block size<description> 
    <property>
    

    但是,您的count 变量是hdfsRead 的返回值。它返回实际读取的字节数,如果在读取过程中到达文件末尾,则该字节数可能小于缓冲区的长度。 您似乎受到客户端代码中的最大值的限制。 hdfsread 中缓冲区的最大长度是tSize 的最大大小。检查tsize 是否为uint16_t,您每次最多可以读取 65535 个字节。通过sizeOf(tSize)检查tSize的长度。

    另外客户端在HDFS中写入的默认包大小是65535,所以尽量不要以写入模式打开文件,直接使用O_RDONLY看看效果。

    【讨论】:

    • 感谢您的回答,但 sizeOf(tSize) = 4 。另外,我在附加的示例代码中使用了 O_RDONLY。
    • 您也使用 O_CREAT。取下来看看效果。
    • 没有 O_CREAT 的行为相同。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多