【解説】WebHDFSにgetmergeがない理由

★悩み★
・WebHDFSではどのような操作ができるのだろうか。
・WebHDFSにgetmerge相当のコマンドはないのだろうか。
・WebHDFSを使ってgetmergeを実現するにはどうすればいいのだろうか。

こういった「悩み」に答えます。

★本記事の内容★
(1) WebHDFSでは13つの操作が可能【実機検証あり】
(2) WebHDFSではgetmerge相当の操作はできません
(3) WebHDFSでgetmergeを実現する方法をご紹介

この記事を書いてる筆者は、4年間、データエンジニアとして従事しています。

データエンジニアとして、HDFS関連の運用保守であったり、HDFS関連の技術を用いたデータ基盤の提案や導入をしたりしてきました。

また、趣味としてHDFSを活用したSNS分析も行なっています。
分析内容に興味がある方は、下記の記事を参照してみてください。

HDFS(Hadoop)を普段から使い続けてはや4年な筆者が、「WebHDFSにgetmergeがない理由」に関して分かりやすく解説していきます。

WebHDFSでは13つの操作が可能【実機検証あり】

WebHDFSでは13つの操作ができるとHadoop公式サイトに記載されています。

WebHDFSとは何か?を知りたい」や「WebHDFSの代表的な操作の実行結果を知りたい」を方は、下記の記事に詳しく記載していますので参照してみてください。

今回は、上記記事で紹介していない下記の9つの操作をご紹介します。

★ご紹介する操作について★
(1) Create and Write to a File 【上記記事でご紹介済み】
(2) Append to a File 【上記記事でご紹介済み】
(3) Concat File(s)
(4) Open and Read a File 【上記記事でご紹介済み】
(5) Make a Directory
(6) Create a Symbolic Link
(7) Rename a File/Directory
(8) Delete a File/Directory 【上記記事でご紹介済み】
(9) Truncate a File
(10) Status of a File/Directory
(11) List a Directory
(12) List a File
(13) Iteratively List a Directory

(3) Concat File(s)

HDFS上にある複数のファイルを1つのファイルに結合することができます。

$ hadoop fs -ls blog
Found 2 items
-rw-r--r--   1 hadoop supergroup          2 2020-09-11 20:56 blog/sample.txt
-rw-r--r--   1 hadoop supergroup          2 2020-09-11 20:56 blog/sample2.txt
$ hadoop fs -cat blog/sample.txt
a
$ hadoop fs -cat blog/sample2.txt
b
$ curl -i -L -X POST  "http://master1:9870/webhdfs/v1/user/hadoop/blog/sample.txt?op=CONCAT&user.name=hadoop&sources=/user/hadoop/blog/sample2.txt"
$ hadoop fs -cat blog/sample.txt
a
b
$ hadoop fs -ls blog
Found 1 items
-rw-r--r--   1 hadoop supergroup          4 2020-09-11 20:56 blog/sample.txt

結合対象となったファイル(上記だとsample2.txt)は、削除されます。

(5) Make a Directory

HDFS上にディレクトリを作成することができます。

$ hadoop fs -ls blog
ls: `blog': No such file or directory
$ curl -i -X PUT "http://master1:9870/webhdfs/v1/user/hadoop/blog?op=MKDIRS&user.name=hadoop"
$ hadoop fs -ls blog
$

(6) Create a Symbolic Link

HDFS上にシンボリックリンクを作成することができます。

$ curl -i -X PUT "http://master1:9870/webhdfs/v1/user/hadoop/blog?op=CREATESYMLINK&user.name=hadoop&destination=/link"
{"RemoteException":{"exception":"UnsupportedOperationException","javaClassName":"java.lang.UnsupportedOperationException","message":"Symlinks not supported"}}

hadoop3.2.1だとシンボリックリンクの作成は、サポートされていないようです。

(7) Rename a File/Directory

HDFS上にあるファイルやディレクトリの名称を変更することができます。

$ hadoop fs -mkdir blog
$ hadoop fs -ls blog
$ curl -i -X PUT "http://master1:9870/webhdfs/v1/user/hadoop/blog?op=RENAME&destination=/user/hadoop/blog2&user.name=hadoop"
{"boolean":true}
$ hadoop fs -ls blog2
$ 

(9) Truncate a File

HDFS上にあるファイルに対して、newlengthに指定した位置以降の文字を削除します。

$ hadoop fs -cat blog2/sample.txt
abcdefg
$ curl -i -X POST "http://master1:9870/webhdfs/v1/user/hadoop/blog2/sample.txt?op=TRUNCATE&newlength=1&user.name=hadoop"
$ hadoop fs -cat blog2/sample.txt
a
$ 

(10) Status of a File/Directory

HDFS上にあるファイルやフォルダのステータスを表示します。

$ curl -i  "http://master1:9870/webhdfs/v1/user/hadoop/blog2/sample.txt?
{"FileStatus":{"accessTime":1599826922830,"blockSize":134217728,"childrenNum":0,"fileId":82178,"group":"supergroup","length":1,"modificationTime":1599827017457,"owner":"hadoop","pathSuffix":"","permission":"644","replication":1,"storagePolicy":0,"type":"FILE"}}
$ 

(11) List a Directory/(12) List a File

HDFS上のあるディレクトリ内にあるディレクトリとファイルの一覧を表示します。

$ curl -i  "http://master1:9870/webhdfs/v1/user/hadoop/blog2?op=LISTSTATUS&user.name=hadoop"
{"FileStatuses":{"FileStatus":[
{"accessTime":1599826922830,"blockSize":134217728,"childrenNum":0,"fileId":82178,"group":"supergroup","length":1,"modificationTime":1599827017457,"owner":"hadoop","pathSuffix":"sample.txt","permission":"644","replication":1,"storagePolicy":0,"type":"FILE"},
{"accessTime":1599827625541,"blockSize":134217728,"childrenNum":0,"fileId":82179,"group":"supergroup","length":2,"modificationTime":1599827625651,"owner":"hadoop","pathSuffix":"sample2.txt","permission":"644","replication":1,"storagePolicy":0,"type":"FILE"}
]}}
$ 

(13) Iteratively List a Directory

HDFS上にあるディレクトリに関して再帰的な一覧を表示します。

$ curl -i  "http://master1:9870/webhdfs/v1/user/hadoop/blog2?op=LISTSTATUS_BATCH&user.name=hadoop"
{"DirectoryListing":{"partialListing":{"FileStatuses":{"FileStatus":[{"accessTime":0,"blockSize":0,"childrenNum":1,"fileId":82180,"group":"supergroup","length":0,"modificationTime":1599827973159,"owner":"hadoop","pathSuffix":"blog","permission":"755","replication":0,"storagePolicy":0,"type":"DIRECTORY"},{"accessTime":1599826922830,"blockSize":134217728,"childrenNum":0,"fileId":82178,"group":"supergroup","length":1,"modificationTime":1599827017457,"owner":"hadoop","pathSuffix":"sample.txt","permission":"644","replication":1,"storagePolicy":0,"type":"FILE"},{"accessTime":1599827625541,"blockSize":134217728,"childrenNum":0,"fileId":82179,"group":"supergroup","length":2,"modificationTime":1599827625651,"owner":"hadoop","pathSuffix":"sample2.txt","permission":"644","replication":1,"storagePolicy":0,"type":"FILE"}]}},"remainingEntries":0}}
$ 

以上が実機で操作してみた結果となります。

WebHDFSではgetmerge相当の操作はできません!

以下のようにgermergeコマンドを実行すると、HDFS上のあるディレクトリ内にある全ファイルを1つにした上でローカルファイルシステムへコピーすることができます。

$ hadoop fs -getmerge blog2 test.txt
$ hadoop fs -cat blog2/sample.txt
a
$ hadoop fs -cat blog2/sample2.txt
b
$ cat test.txt 
ab
$ 

結論から言いますと、「WebHDFSではgetmerge相当の機能は用意されていません」。

なぜ、WebHDFSにはgetmerge相当の機能が用意されていないのかを理解するために、getmerge部分のソースコードを読んでみました。

getmerge部分のソースコード理解について

getmerge部分のソースコードは、ここに公開されています。

getmergeコマンドは、約100行程度で実装されています。
特にコア部分は、以下の部分になります。

    protected void processArguments(LinkedList<PathData> items)
    throws IOException {
      super.processArguments(items);
      if (exitCode != 0) { // check for error collecting paths
        return;
      }
      FSDataOutputStream out = dst.fs.create(dst.path); (1)
      try {
        for (PathData src : srcs) { (2)
          if (src.stat.getLen() != 0) {
            try (FSDataInputStream in = src.fs.open(src.path)) {
              IOUtils.copyBytes(in, out, getConf(), false); (3)
              writeDelimiter(out);
            }
          } else if (!skipEmptyFileDelimiter) {
            writeDelimiter(out);
          }
        }
      } finally {
        out.close(); (4)
      }
    }

簡単にアルゴリズムの流れに関してご説明します。

★getmergeのアルゴリズムについて★

FSDataOutPutStreamクラスに関しては、ここにリファレンスがあります。
リファレンスやソースコードを読み解くと、(1)の部分でローカルファイルシステムに空のファイルを作成します。

PathDataクラスに関しては、ここにリファレンスがあります。
リファレンスやソースコードを読み解くと、(2)の部分では、HDFS上の指定したディレクトリ配下にある全てのファイルで(3)を繰り返し処理します。

IOUtilsクラスに関しては、ここにリファレンスがあります。
リファレンスやソースコードを読み解くと、(3)の部分では、(1)で作成した空のファイルに対して、HDFS上にあるファイルをコピーしています。

最後に(4)の部分でファイル操作の後処理をすることで、ローカルファイルシステム上にHDFS上のファイルをマージした1つのファイルが作成されます。

getmergeのソースコードを読み解くと、getmergeコマンドは、端末のリソース(メモリやCPU)を利用する処理だということが分かります。

WebHDFSは、HTTP経由でHDFSにアクセスできるため、リソースが潤沢ではないスマートフォンなどからもアクセスできます。
仮にWebHDFSにおいてgetmerge相当の機能が実装されていた場合、リソースが潤沢でない端末でgetmerge相当の機能を実行してしまうと、最悪の場合、その端末のリソースを食い尽くし機能不全な状態になってしまいます。

そういうことを危惧したため、WebHDFSにgetmerge相当の機能を実装しなかったのかもしれません。

WebHDFSでgetmergeを実現する方法

WebHDFSでgetmerge相当の機能を使いたいという声は多々あります。

結論としては、以下のどちらかの方法を使えば、WebHDFSでgetmerge相当の機能を使うことができます。

★WebHDFSでgetmerge相当の機能を使う方法★
(A) (3) Concat File(s)と(12) List a Fileを組み合わせて実現する方法
(B) (12) List a FileとJavascriptを組み合わせて実現する方法

上記のどちらかを採用することで、WebHDFSでgetmerge相当の機能を使うことができます。

(A)と(B)の実装方法に関しては、また後日の記事でご紹介します。

【まとめ】WebHDFSにgetmergeがない理由

今回の記事を通して、getmergeの実装アルゴリズムをご紹介することで、以下の悩みを解消しました。

★悩み★
・WebHDFSではどのような操作ができるのだろうか。
・WebHDFSにgetmerge相当のコマンドはないのだろうか。
・WebHDFSを使ってgetmergeを実現するにはどうすればいいのだろうか。

WebHDFSでgetmergeがない理由は何?と悩んでいるあなた」にこの記事が少しでも役に立てれば幸いです。

コメント