HDFS(Hadoop Distributed File System)とは

hadoop

HDFSとは

Hadoopの分散ファイルシステム。 Hadoopのファイルシステム実装の一つで、他の実装にはLocal fileやS3などがある。 データのサイズが大きい場合に特に問題となるディスクI/Oを分散させ、読み書きする最小の単位であるブロックサイズを大きくしシークのコストを減らすことで スループットを高めている。

ディスクI/Oのオーバーヘッドがどれくらい大きいかというと、データセンター内での通信が往復0.5msほどで行われるのに対して、 シークは10ms、1MBの読み込みは20msもかかる

1ファイルあたり150バイトのメタデータがNameNodeのメモリ上に乗るので大量のファイルを扱うのは得意ではない。また、ファイルは追記しかできない。

NameNodeとDataNode

クラスタ内にはブロックを分散して持つDataNodeと、どのDataNodeにそのファイルのブロックがあるかを管理する名前空間ごとのNameNodeが存在する。 NameNodeはファイルのメタデータのスナップショットであるfsimageと、fsimageにまだ含まれていない変更ログであるedit logを持っている。 edit logは定期的にSecondary NameNodeによってfsimageにマージされる。

NameNodeが機能停止すると読み書きできなくなってしまうので新しいNameNodeを立てる必要がある。 その際fsimageにedit logを適用して状態を復元するため、これらのファイルは別のファイルシステムにバックアップなどして失われないようにする。

巨大なクラスタだとNameNodeを立ち上げるのに30分以上かかることもあるため、 Secondary NameNodeの代わりにStandby NameNodeを立てて可用性を高めることもできる。 Standby NameNodeはNameNodeと共有ストレージでedit logを共有し、最新の状態がメモリ上に乗っているのでNameNodeが死んだと判断されてから数十秒ほどで切り替えることができる。

書き込みと読み込み

書き込み

ファイルシステムがNameNodeとやりとりして、ファイルが存在しているか、パーミッションがあるかを確認し、問題なければFSDataOutputStreamをクライアントに返す。書き込むデータはまずキューに入れられ、どのDataNodeに書き込むかはDataStreamerというのがNameNodeとやりとりして決める。 DataNodeはレプリカの設定数分選ばれ、順に書き込まれるようDataNode間でパイプラインが作られる。 正常に書き込まれたDetaNodeからはackパケットが返ってくるのでこれはackキューに入れて全て正しく書き込まれたことが確認できたら消す。 失敗したDataNodeがあったら、そこに中途半端に書き込まれた分を消して、パイプラインから除き新しいパイプラインを作る。

読み込み

ファイルシステムがNameNodeにファイルのブロックがどこにあるかを問い合わせる。 NameNodeはブロックがあるDataNodeをクライアントからネットワークトポロジ上で近い順にソートしてアドレスを返す。 ファイルシステムはそのアドレスが含まれたFSDataInputStreamをクライアントに返してクライアントが順にreadしていく。

SingleNode Clusterで動かす

$ yum --enablerepo=epel -y install pdsh
$ echo $JAVA_HOME
/usr/lib/jvm/jre
$ wget http://ftp.jaist.ac.jp/pub/apache/hadoop/common/hadoop-2.7.3/hadoop-2.7.3.tar.gz
$ tar xvzf hadoop-2.7.3.tar.gz 
$ cd hadoop-2.7.3
$ bin/hadoop version
Hadoop 2.7.3

デフォルトのファイルシステムをHDFSにしてレプリカを1にする。

$ vi etc/hadoop/core-site.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
...
<configuration>
    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://localhost:9000</value>
    </property>
</configuration>

$ vi etc/hadoop/hdfs-site.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
...
<configuration>
    <property>
        <name>dfs.replication</name>
        <value>1</value>
    </property>
</configuration>

Hadoopデーモンを起動/終了させるためにsshできるようにする。

$ ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa
$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
$ chmod 0600 ~/.ssh/authorized_keys
$ ssh localhost

起動。

$ bin/hdfs namenode -format
$ sbin/start-dfs.sh
localhost: starting namenode, ...
localhost: starting datanode, ...
0.0.0.0: starting secondarynamenode, ...

ディレクトリやファイルを作成して参照する。

$ bin/hdfs dfs -mkdir /home
$ bin/hdfs dfs -mkdir /user/ec2-user
$ echo 'aaaaa' > hoge
$ bin/hdfs dfs -put hoge ./
$ bin/hdfs dfs -put hoge ./
put: `hoge': File exists

$ bin/hdfs dfs -appendToFile hoge hoge
$ bin/hdfs dfs -ls ./
Found 1 items
-rw-r--r--   1 ec2-user supergroup         12 2017-08-14 13:44 hoge

$ bin/hdfs dfs -cat hoge
aaaaa
aaaaa

Filesystem check utilityを実行する。

$ bin/hdfs fsck ./ -files -blocks
Connecting to namenode via http://localhost:50070/fsck?ugi=ec2-user&files=1&blocks=1&path=%2Fuser%2Fec2-user
FSCK started by ec2-user (auth:SIMPLE) from /127.0.0.1 for path /user/ec2-user at Mon Aug 14 13:44:48 UTC 2017
/user/ec2-user <dir>
/user/ec2-user/hoge 12 bytes, 1 block(s):  OK
0. BP-478671077-172.31.3.159-1502715364675:blk_1073741825_1002 len=12 repl=1

Status: HEALTHY
 Total size:	12 B
 Total dirs:	1
 Total files:	1
 Total symlinks:		0
 Total blocks (validated):	1 (avg. block size 12 B)
 Minimally replicated blocks:	1 (100.0 %)
 Over-replicated blocks:	0 (0.0 %)
 Under-replicated blocks:	0 (0.0 %)
 Mis-replicated blocks:		0 (0.0 %)
 Default replication factor:	1
 Average block replication:	1.0
 Corrupt blocks:		0
 Missing replicas:		0 (0.0 %)
 Number of data-nodes:		1
 Number of racks:		1
FSCK ended at Mon Aug 14 13:44:48 UTC 2017 in 2 milliseconds

参考

Hadoop: The Definitive Guide, 4th Edition

A Guide to Checkpointing in Hadoop – Cloudera Engineering Blog