どぅーちゅいむーにー

これ、Twitterでよくね?という日々の記録かも

Hadoopの基本的なメモ

  • インストール関連

セットアップに関しては、↓の連載と本家を参考にしました。
http://codezine.jp/article/detail/2485

本家、スタートアップ↓
http://hadoop.apache.org/common/docs/current/quickstart.html


  • そのた参照

コマンドリファレンス
http://hadoop.apache.org/common/docs/r0.20.0/commands_manual.html



  • その他、基本的なメモ。

クラスタ構成で起動する場合、masterノードにて、start-all.shを実行する。
また、起動直後は safe mode となっているので、そのあたりを確認する。

今のモード確認は % hadoop dfsadmin -sfaemode get を実行。

% hadoop dfsadmin -safemode get
Safe mode is OFF

safe mode が ON の場合、書き込み、削除ができない。


また、各マシンで jps を発行することで起動しているプロセスを知ることができます。
↓myhdfs1(master)で実行

myhdfs1> jps
23361 JobTracker
4509 Jps
23288 SecondaryNameNode
23168 DataNode
23052 NameNode
23479 TaskTracker
myhdfs1>



↓myhdfs2(slave)で実行

myhdfs2> jps
8411 DataNode
8501 TaskTracker
19314 Jps

実のところ、myhdfs3でjpsを実行したところ、Jpsしか表示されず。
ん〜、なんだかんだ、よくわかりません・・・

  • -

Update History:
2010.04.20:新規作成

試した環境メモ

今回は、3台のデスクトップPCに入れたCentoOS上でいろいろとやってみることにしました。


試した Hadoop のバージョンは 0.20.2 です。
後々、バージョンアップするときはまた書こうと思います。


Hadoop構築にあたっては、クラスタを構成するマシン間でsshのパスワードなしログインができる必要があるみたいなのですが、/etc/sysconfig/network に書かれたホスト名と異なる名前を /etc/hosts につけて構築したため、ちょっと怪しい感じがしたのは内緒です。


/etc/hostsの内容(masterノード)

172.29.11.111   myhdfs1 xxx
172.29.11.112   myhdfs2 yyy
172.29.11.113   myhdfs3 zzz zzz.domain.co.jp

xxx、yyy、zzzが hostname に対応。
HDFSクラスタとしては、myhdfs? を使用(masters, slavesファイルには myhdfs? を記述)。
ちなみに、112/113のマシンはCentOS release 5.3 (Final)で、113だけCentOS release 4.5 (Final)となってます。

Hadoopを起動すると、Webからファイルを参照することができるのですが、そこでは hostname のほうが表示されるんですよねー。
NameNodeへのアクセス↓

http://NameNodeホスト:50070/dfshealth.jsp

※本家、Quick Startにちらっと書かれています


今回使ったマシンは、別のプロジェクトで実際に使用しているものを間借りしているのでしょうがないというところです。


また、レプリケーション(ファイルのコピーをいくつ用意するのか?)については、3台構成ですし、2つにしてみました。

myhdfs1> cat hdfs-site.xml
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>

<!-- Put site-specific property overrides in this file. -->


  
    dfs.replication
    2
  


※都合上、全角文字にしたものがあります。まだ「はてな」に慣れていないもので・・・

HDFSの基本的なメモ

Hadoopをインストール、セットアップして起動したあと、適当にいじってみる。

  • 参照

Shellコマンドで。
http://hadoop.apache.org/common/docs/current/hdfs_shell.html
HDFS自体のユーザガイド
http://hadoop.apache.org/common/docs/current/hdfs_user_guide.html

  • Shellから操作いろいろ

1)やっぱ基本はls

myhdfs1> hadoop fs -ls /
Found 2 items
drwxr-xr-x   - issei supergroup          0 2010-04-19 18:03 /home
drwxr-xr-x   - issei supergroup          0 2010-04-19 18:30 /tmp

たしか、/tmp と /home は別に作った気がする。
この結果は、myhdfs1/2/3 いずれのマシンで実行しても同じです。まぁ、そうでなくては困りますが。


2)ディレクトリを作ってみる。

myhdfs1> hadoop fs -ls /home/issei/
Found 1 items
drwxr-xr-x   - issei supergroup          0 2010-04-19 19:53 /home/issei/work
myhdfs1> hadoop fs -mkdir /home/issei/tmp
myhdfs1> hadoop fs -ls /home/issei/
Found 2 items
drwxr-xr-x   - issei supergroup          0 2010-04-20 10:30 /home/issei/tmp
drwxr-xr-x   - issei supergroup          0 2010-04-19 19:53 /home/issei/work
myhdfs1>

まぁ、一般的なShellと同じかと。


3)都合が悪いのでHDFS上のディレクトリをリネームしてみる。
まぁ、CentOS上のディレクトリ構成も /home/issei とかになっていたりすると、自分でもこんがらがいそうな気がするので、HDFS上のディレクトリ名を変更してみる。

myhdfs1> hadoop fs -ls /home
Found 1 items
drwxr-xr-x   - issei supergroup          0 2010-04-20 10:30 /home/issei
myhdfs1> ls
app  tmp  work
myhdfs1> hadoop fs -ls /home
Found 1 items
drwxr-xr-x   - issei supergroup          0 2010-04-20 10:30 /home/issei
myhdfs1> hadoop fs -mv /home/ /hdhome
myhdfs1> hadoop fs -ls /
Found 2 items
drwxr-xr-x   - issei supergroup          0 2010-04-19 18:03 /hdhome
drwxr-xr-x   - issei supergroup          0 2010-04-19 18:30 /tmp
myhdfs1> hadoop fs -ls /hdhome/issei
Found 2 items
drwxr-xr-x   - issei supergroup          0 2010-04-20 10:30 /hdhome/issei/tmp
drwxr-xr-x   - issei supergroup          0 2010-04-19 19:53 /hdhome/issei/work
myhdfs1> hadoop fs -mv /hdhome/issei /hdhome/k155e1
myhdfs1> hadoop fs -ls /hdhome/
Found 1 items
drwxr-xr-x   - issei supergroup          0 2010-04-20 10:30 /hdhome/k155e1

そんなわけで、実ファイルシステム(?)は、/home/issei/ で、HDFS上のパスは /hdhome/k155e1/ にしてみました。


4)ファイルを投入してみる。
ファイルを投入する場合、copyFromLocal とか moveFromLocal を実行して、ローカルのファイルシステムからHDFS上にコピー・移動する感じです。

myhdfs1> pwd
/home/issei/local
myhdfs1> ls
hello.txt
myhdfs1> cat hello.txt
Hello World!

This is test file for HDFS test.

で、これをHDFS上にコピーして、中身を確認(cat)してみる。

myhdfs1> pwd
/home/issei/local
myhdfs1> ls
hello.txt
myhdfs1> hadoop fs -ls /hdhome/k155e1/tmp
myhdfs1> hadoop fs -copyFromLocal hello.txt /hdhome/k155e1/tmp
myhdfs1> hadoop fs -ls /hdhome/k155e1/tmp
Found 1 items
-rw-r--r--   2 issei supergroup         48 2010-04-20 10:42 /hdhome/k155e1/tmp/hello.txt
myhdfs1> hadoop fs -cat /hdhome/k155e1/tmp/hello.txt
Hello World!

This is test file for HDFS test.

myhdfs1>

以上、ローカルファイルシステムからのコピーと、cat の使い方、という感じ。


5)で、実際のファイルシステム上はどうなっているのか?
まだ、細かいところまで調べきれていないのですが、ファイルは /tmp/hadoop-ユーザID/ あたりに保存されます。まぁ、他にも /tmp 以下にファイルはあるのですが。
今回(ユーザIDはissei)の場合、怪しいところをたどっていくとこんな感じになりました。

myhdfs1> ls /tmp/hadoop-issei
hadoop-issei/                       hadoop-issei-namenode.pid
hadoop-issei-datanode.pid           hadoop-issei-secondarynamenode.pid
hadoop-issei-jobtracker.pid         hadoop-issei-tasktracker.pid
myhdfs1> ls /tmp/hadoop-issei/
dfs  mapred
myhdfs1> ls /tmp/hadoop-issei/
dfs  mapred
myhdfs1> ls /tmp/hadoop-issei/dfs/
data  name  namesecondary
myhdfs1> ls /tmp/hadoop-issei/dfs/data/
current  detach  in_use.lock  storage  tmp
myhdfs1> ls /tmp/hadoop-issei/dfs/data/current/
VERSION                             blk_101486462659419571             subdir0
blk_-137371469502402326             blk_101486462659419571_1080.meta   subdir1
blk_-137371469502402326_1055.meta   blk_1505310026847830224            subdir10
blk_-1949842581763971189            blk_1505310026847830224_1035.meta  subdir11
blk_-1949842581763971189_1072.meta  blk_1746935554941452270            subdir12
... この間にたくさんのファイル ...
blk_-869827101370329721_1079.meta   blk_912974557086589529             subdir8
blk_-9022076184702837969            blk_912974557086589529_1076.meta   subdir9
blk_-9022076184702837969_1075.meta  dncp_block_verification.log.curr
myhdfs1>

実際にどのサーバにファイルが保存されているのか?については、また追って調べてみたいと思っています。


6)まとめ?
HDFSをShellで操作するという点については、こんなところかと。
Unix Shellを使っている人にとってはあまり違和感ない感じですね。
あとは HDFS File System Shell Guide↓でどのようなことができるかは把握できると思います。
http://hadoop.apache.org/common/docs/current/hdfs_shell.html
hadoop fs -ls とかを hdls とか alias 定義しておけば、もっと楽になる感じかと。


そんなわけで、本エントリはこんなところで。

NameNodeにブラウザからアクセス

というわけで、1つ前のエントリ(d:id:k155e1:20100420:1271728950)で準備したHDFS上のファイルを、ブラウザから見てみる。


http://myhdfs1:50070/でアクセスしたときの画面表示(myhdfs1がmasterノードです)



Browse the filesystemというリンクをクリック。
ルートディレクトリの情報がみれます。



で、/hdhome/k155e1/tmp/ に移動してみます。
hello.txtがあることがわかります。



hello.txt をクリックすると、中身がみれます。



よくみると、hello.txt の中身を参照する画面の下のほうに以下のような記述あり。
これは、myhdsf1(111のほう)とmyhdfs2(同112)に保存されているっていうこと?
実際は IP:ポートの部分は両方ともリンクになっています。

Total number of blocks: 1
1480257331636962015:   172.29.11.112:50010   172.29.11.111:50010 

このあたりはもうちょっと調べてみますが、
クリックすると、同じく hello.txt の表示画面なのですが、111(myhdfs1)のほうはアドレスが

http://myhdfs1:50075/browseBlock.jsp?blockId=....

となり、112(myhdfs2)のほうをクリックすると同じくhello.txtの表示画面でアドレスが

http://myhdfs2:50075/browseBlock.jsp?blockId=....

となります。
このあたりについては、実際 NameNode にリクエストするプログラムとか作ってみて、試してみる予定(いつぐらいになるかは未定・・・)。


いぢょ、こんなところで。

ZooKeeper 3.3.0 のインストール

HBaseをインストールするためにはZooKeeperというものをインストールする必要があるらしい。
というわけで、ZooKeeper というものをインストール。
っていうか、けっこう書いてたのに左側の「はてなダイアリープラス」のバナーを間違ってクリックしたらすべてが吹っ飛んだ・・・

  • インストールしたバージョン

今回、試したバージョンは 3.3.0 です。


なお、インストールに関して、Hadoop は不要のようです(たぶん)。

  • 概要とか

Hadoop のサブプロジェクトの1つです。
公式:http://hadoop.apache.org/zookeeper/
日本語の概要:http://oss.infoscience.co.jp/hadoop/zookeeper/index.html
「分散アプリケーションのためのパフォーマンスの高いコーディネーションサービス」ということですが、まだちょっとピンときてません。
分散処理におけるトランザクション管理とかそういうたぐいのものかと思いますが、まぁ、現時点ではそれが目的ではないので、未来にゆだねたいと思います。

  • インストール

ダウンロードして、解凍、設定ちょっといじって完了といういい感じな手順となっています。
インストール先は /home/issei/app/zookeeper-3.3.0/ になりました。
ですので、以下、ディレクトリは上記ディレクトリからの相対パスとなります。

設定ファイルは以下のようにしました

myhdfs1> cat zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/home/issei/tmp/zookeeper
clientPort=2181

サンプル(conf/zoo_sample.cfg)をコピーして、コメントを削除した感じです。
ドキュメントのページには initLimit と syncLimit については触れられていません。ので、サンプルのままとなっています("tick"のニュアンスがまだピンとこないので、とりあえずそのままということで・・・)。


分散モード?で実行するためには追加で設定を行う必要があるみたいですが、まぁ、現時点ではこれがメインというわけではないので、次の機会にとっておくことにします。一応、Getting Started の最後のほうに書いてあるみたい。

  • 実行してみる。

bin ディレクトリに sh あり。環境設定の sh もチェックしつつ、ドキュメントもみてみましたが、JAVA_HOME を設定する必要があるとか、そういう話は書いていないっぽい。ので、

myhdfs1> bin/zkServer.sh start

で起動する。
起動するとコンソールにログがつらつらと出力されます。

  • ログに関して

conf/log4j.properties があります。デフォルトで、rootLogger の設定が

# DEFAULT: console appender only
log4j.rootLogger=INFO, CONSOLE

となっていますので、ファイルには出力されません。
が、ファイルへの書き込み(RollingFileAppender)も定義されているみたいですので、実際にはコメントアウトされている

# Example with rolling log file
#log4j.rootLogger=DEBUG, CONSOLE, ROLLINGFILE

のほうを有効にすれば良いかと思います(試していませんが)。

  • 停止

停止するには、起動時に使用した zkServer.sh に stop を与えて実行するらしい。
最初、Ctrl-C してみたのですが、クライアントから接続(後述)してみると起動した状態でした。


以下、jps でプロセスを確認して、zkServer.sh stop を実行し、再度 jps で確認、という流れ。

myhdfs1> jps
6856 Jps
23361 JobTracker
23288 SecondaryNameNode
23168 DataNode
5615 QuorumPeerMain
23052 NameNode
23479 TaskTracker
myhdfs1> ./bin/zkServer.sh  stop
JMX enabled by default
Using config: /home/issei/app/zookeeper-3.3.0/bin/../conf/zoo.cfg
Stopping zookeeper ...
STOPPED
myhdfs1> jps
6910 Jps
23361 JobTracker
23288 SecondaryNameNode
23168 DataNode
23052 NameNode
23479 TaskTracker
[issei@cgp1 bin]$

という感じ。5615 QuorumPeerMainがなくなっていることがわかります。

  • とりあえず接続してみる

Cのクライアントもあるようですが、とりあえず今回は Java のほうで。

myhdfs1> ./bin/zkCli.sh -server 127.0.0.1:2181
Connecting to 127.0.0.1:2181
2010-04-20 18:03:10,245 - INFO  [main:Environment@97] - Client environment:zookeeper.version=3.3.0-925362, built on 03/19/2010 18:38 GMT
2010-04-20 18:03:10,251 - INFO  [main:Environment@97] - Client environment:host.name=xxx.yyy.zzz
2010-04-20 18:03:10,252 - INFO  [main:Environment@97] - Client environment:java.version=1.6.0_18
2010-04-20 18:03:10,253 - INFO  [main:Environment@97] - Client environment:java.vendor=Sun Microsystems Inc.
2010-04-20 18:03:10,254 - INFO  [main:Environment@97] - Client environment:java.home=/usr/local/jdk1.6.0_18/jre
... ログが続く ...
2010-04-20 18:03:10,321 - INFO  [main-SendThread():ClientCnxn$SendThread@1000] - Opening socket connection to server /127.0.0.1:2181
Welcome to ZooKeeper!
JLine support is enabled
2010-04-20 18:03:10,373 - INFO  [main-SendThread(サーバ名:2181):ClientCnxn$SendThread@908] - Socket connection established to サーバ名/127.0.0.1:2181, initiating session
2010-04-20 18:03:10,391 - INFO  [main-SendThread(サーバ名:2181):ClientCnxn$SendThread@701] - Session establishment complete on server サーバ名/127.0.0.1:2181, sessionid = 0x1281a050e570002, negotiated timeout = 30000

WATCHER::

WatchedEvent state:SyncConnected type:None path:null
[zk: 127.0.0.1:2181(CONNECTED) 0]

で、最後の[zk: 127.0.0.1:2181(CONNECTED) 0]がプロンプトになります。
help と打つとヘルプが出力されます。

[zk: 127.0.0.1:2181(CONNECTED) 0] help
ZooKeeper -server host:port cmd args
        connect host:port
        get path [watch]
        ls path [watch]
        set path data [version]
        delquota [-n|-b] path
        quit
        printwatches on|off
        create [-s] [-e] path data acl
        stat path [watch]
        close
        ls2 path [watch]
        history
        listquota path
        setAcl path acl
        getAcl path
        sync path
        redo cmdno
        addauth scheme auth
        delete path [version]
        setquota -n|-b val path
[zk: 127.0.0.1:2181(CONNECTED) 1] quit
Quitting...
2010-04-20 18:03:12,212 - INFO  [main:ZooKeeper@538] - Session: 0x1281a050e570002 closed
myhdfs1>

とりあえず、つないで、quit で抜けた、というところ。

続きは次回。

CLIクライアントからのテスト

そんなわけで前回(d:id:k155e1:20100420:1271755120)に引き続き ZooKeeper(バージョンは 3.3.0)の話ですが、以下、Getting Startedのサンプルをそのまま実行しただけのログです。

  • その前に

log4j.properties でファイルへのログを有効にしてみた。

# Format is "<default threshold> (, <appender>)+

# DEFAULT: console appender only
#log4j.rootLogger=INFO, CONSOLE

# Example with rolling log file
log4j.rootLogger=DEBUG, CONSOLE, ROLLINGFILE

デフォルトをコメントアウトして、ROLLINGFILE を有効にしただけですが。
ログファイルのパスは

log4j.appender.ROLLINGFILE.File=/home/issei/app/logs/zookeeper.log



んで、起動。

myhdfs1> pwd
/home/issei/app/logs
myhdfs1> ls -ltr
合計 12
-rw-rw-r-- 1 issei issei 8782  420 18:35 zookeeper.log
myhdfs1> head -10 zookeeper.log
2010-04-20 18:35:58,573 - INFO  [main:QuorumPeerConfig@90] - Reading configuration from: /home/issei/app/zookeeper-3.3.0/bin/../conf/zoo.cfg
2010-04-20 18:35:58,579 - WARN  [main:QuorumPeerMain@105] - Either no config or no quorum defined in config, running  in standalone mode
2010-04-20 18:35:58,594 - DEBUG [main:AbstractDynamicMBean@124] - preRegister called. Server=com.sun.jmx.mbeanserver.JmxMBeanServer@7d8483, name=log4j:hiearchy=default
2010-04-20 18:35:58,595 - DEBUG [main:HierarchyDynamicMBean@254] - postRegister is called.
2010-04-20 18:35:58,601 - DEBUG [main:AbstractDynamicMBean@124] - preRegister called. Server=com.sun.jmx.mbeanserver.JmxMBeanServer@7d8483, name=log4j:logger=root
2010-04-20 18:35:58,602 - DEBUG [main:LoggerDynamicMBean@256] - Adding AppenderMBean for appender named CONSOLE
2010-04-20 18:35:58,607 - DEBUG [main:AppenderDynamicMBean@152] - getMBeanInfo called.
2010-04-20 18:35:58,609 - DEBUG [main:AppenderDynamicMBean@309] - preRegister called. Server=com.sun.jmx.mbeanserver.JmxMBeanServer@7d8483, name=log4j:appender=CONSOLE
2010-04-20 18:35:58,610 - DEBUG [main:AppenderDynamicMBean@191] - Adding LayoutMBean:CONSOLE,layout=org.apache.log4j.PatternLayout
2010-04-20 18:35:58,613 - DEBUG [main:LayoutDynamicMBean@138] - getMBeanInfo called.
myhdfs1>

という感じで、ファイルに出力されるようになりましたとさ。


本題。

  • ls してみる

接続は前回を参考に、./bin/zkCli.sh -server 127.0.0.1:2181で。
ls /を実行してみる。

[zk: 127.0.0.1:2181(CONNECTED) 0] ls /
[zookeeper]

結果は Getting Started の例と同じ(当たり前ですが)

  • znode を create

例にならい、create /zk_test my_dataを実行してみる。
これは、"my_data" という文字列で関連付けられた znode を生成する、という意味合いらしい。

[zk: 127.0.0.1:2181(CONNECTED) 1] create /zk_test my_data
Created /zk_test
[zk: 127.0.0.1:2181(CONNECTED) 2] ls /
[zookeeper, zk_test]

はい。これも問題ありません。
ちなみに、HDFS へのアクセスと違って、レスポンスはサクサク返ってきます。

  • 中身?を取得

作成した znode /zk_testの中身?を見てみる。

[zk: 127.0.0.1:2181(CONNECTED) 3] get /zk_test
my_data
cZxid = 0xa
ctime = Tue Apr 20 18:42:45 JST 2010
mZxid = 0xa
mtime = Tue Apr 20 18:42:45 JST 2010
pZxid = 0xa
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 7
numChildren = 0

内容はよくわかりません。

  • 更新してみる

"my_data" と関連付けられた、というものを "junk" という文字列に関連付けしてみる。

[zk: 127.0.0.1:2181(CONNECTED) 4] set /zk_test junk
cZxid = 0xa
ctime = Tue Apr 20 18:42:45 JST 2010
mZxid = 0xb
mtime = Tue Apr 20 18:46:12 JST 2010
pZxid = 0xa
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0
[zk: 127.0.0.1:2181(CONNECTED) 5] get /zk_test
junk
cZxid = 0xa
ctime = Tue Apr 20 18:42:45 JST 2010
mZxid = 0xb
mtime = Tue Apr 20 18:46:12 JST 2010
pZxid = 0xa
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0

setしたあとのgetで、mtime(更新日時)が変わっていることがわかります。
1行目が "my_data" でなはなく "junk" になっています。
あとは、dataVersion が 0 から 1 になっているとか、ですかねー。
dataLength は値が変わったので当たり前か。

  • 最後に、削除

そんで、最後にdelete /zk_testで作成した znode を削除してみます。

[zk: 127.0.0.1:2181(CONNECTED) 6] delete /zk_test
[zk: 127.0.0.1:2181(CONNECTED) 7] ls /
[zookeeper]

というわけで、最初の状態に戻りました。



Programmers Guideをみると、クライアントプログラムなどの作成方法などが解説されていますが、とりあえず今回は HBase のほうに進むということで、ZooKeeper についての話はいったんここで終わります。