一台ではえらく簡単だったんだけど
- 複数台では結構つまづいた
- できたけどうまく理解できていない
- できたけど、もっと効率よくできるんじゃないか
などなどあったので記録を取っておく。
複数台のサーバーで(mapとかreduceを)動かすための鍵になるコマンドがあって、それはhadoop dfs。一台で動かしていると(たぶん)使わないコマンド。map&reduceするためのRuby(orその他のスクリプト)をhadoopで動かしたいサーバーに浸透させないといけない。scpなどのコマンドを使って、全てのサーバーにコピー...とかをやるわけではなく(同期とかを考えるとめんどくさそう...)、hadoopがその付近をやってくれるらしい。ついでに言うと、普通のファイルシステム上にコピーとかをしているわけではなく、hadoop上のファイルシステム上にコピーをするようです。そういうわけで「ファイルちゃんと置いてるのに何で読んでくれないの!!」ってなる人もいるかもしれないので注意(自分だった)。
hadoop上のファイルシステムにコピーとかそういう操作をやるコマンドがhadoop dfs。まず、どういう構成とかになっているかとか知りたいと思うので、ls likeな感じで
yasuhisa-y@XXX:/$ hadoop dfs -ls /user/yasuhisa-y Found 3 items -rw-r--r-- 3 yasuhisa-y supergroup 172 2010-05-26 00:53 /user/yasuhisa-y/maper.rb -rw-r--r-- 3 yasuhisa-y supergroup 293 2010-05-26 00:53 /user/yasuhisa-y/reducer.rb drwxr-xr-x - yasuhisa-y supergroup 0 2010-05-26 03:08 /user/yasuhisa-y/word_count_file
としましょう。自分の場合は、すでにいくつか置いてあります。あ、松本研の人は、local wikiに書いてあるように
hadoop dfs -mkdir /user/(自分のアカウント名)
としておきましょう。tmpディレクトリ以下でやってもいいそうですが、再起動とかもしかかったら消えちゃいそうだし、自分の作っておきましょう(たぶん)。
hadoopのファイルシステム上にファイルを置きたい
「自分のローカルにあるファイルをhadoopのファイルシステム上に置きたい!」っていう場合は
hadoop dfs -put hoge.txt /user/yasuhisa-y
などとやると、hadoopのファイルシステム上の/user/yasuhisa-y以下にhoge.txtが配置されます。研究室には(master、slaveを含め)hadoop用のサーバーがいくつかありますが、この操作だけで、どのマシンからやっていてもhadoopのファイルシステム上の/user/yasuhisa-y以下にhoge.txtが配置されます。てら便利。
hadoopのファイルシステム上のファイルを見たい
普通のlinuxとかでcatするのと同じように
hadoop dfs -cat /user/yasuhisa-y/hoge.txt
とできて便利です。ファイルを見たいじゃなくて、ファイルそのものがローカルに欲しいという場合は
hadoop dfs -get /user/yasuhisa-y/hoge.txt .
などとやればカレントディレクトリにhoge.txtがfetchされてくるらしいです。
複数台のサーバー上でhadoopを回したい
これで準備は大体整った(はず)。色々あれこれと試行錯誤してみた結果、こんな感じだととりあえずうまくいきました。やっていることは、日本語版Wikipediaを分かち書きされたもの。このデータは、松本研の人ならhadoopのファイルシステムにすでに置かれています。そうじゃない人は自分で作るか、代替のデータを用意してください。
yasuhisa-y@cacao:/work/yasuhisa-y$ hadoop jar /usr/lib/hadoop/contrib/streaming/hadoop-*-streaming.jar \ -input /nldata/jawiki -output word_count_file 100 -numReduceTasks 100 \ -mapper "maper.rb" -reducer "reducer.rb" -file "maper.rb" -file "reducer.rb"
昨日のエントリにid:mamorukさんがコメントしてくださった(http://d.hatena.ne.jp/syou6162/20100525/1274785616#c1274798747)ように、mapperとreducerのスクリプトをhadoopのファイルシステム上に置いていると、そっちを変更する度にhadoop dfs -rm & hadoop dfs -putしないといけないので激しく面倒です。しかし、hadoop側でこれを自動でやってくれる仕組みがあるそうで、-fileオプションを使うとうまくやってくれます。
さて、そうするとログに
10/05/26 11:30:26 INFO streaming.StreamJob: Tracking URL: http://XXX.naist.jp:50030/jobdetails.jsp?jobid=job_201005202253_0095
というような行があって、mapとreduceの進行状況をブラウザから見ることができます。こんな感じのグラフとかで見れて便利。
上のグラフと見ても分かるのですが、reducerはmapperのjobが100%完了しなくても動き始めます。まあ、数数えるだけだからmapper終わらなくってもreducer開始できますよね。動かないとかエラーが起こったときもここからtrackingできるらしいです(あるいは/var/log/hadoop以下にlogファイルがあるので、そっちでも)。
その他、いくつか箇条書きで書いていくと
- mapperとreducerの数を"100 100"と指定すればmapperとreducerの数が指定できる...はず
- と思ったけど、mapperは勝手に192個とかに設定されていて、reducerは1つに指定されていた
- reducerの数に関しては"-numReduceTasks 100"とやって指定した
- wikipediaくらいのデータだとreducer 1つだと待ってるのがだる(ry
reducerまでやった結果はoutputで指定したディレクトリに吐かれていて
yasuhisa-y@cacao:/work/yasuhisa-y$ hadoop dfs -ls /user/yasuhisa-y/word_count_file
で調べられますね。上ではreducer 100個指定したので、partなんとかってファイルが100個吐かれています。ローカルのファイルに一個ずつgetしてくるのはだるいので、rubyとか(なんでもいいですが)を使ってこんな感じでやれば取ってこれます。
yasuhisa-y@XXX:/work/yasuhisa-y$ ruby -e "(0..99).each{|i| system(\"hadoop dfs -get /user/yasuhisa-y/word_count_file/part-%000005d . \"%i) }" yasuhisa-y@XXX:/work/yasuhisa-y$ ls maper.rb part-00006 part-00013 part-00020 part-00027 part-00034 part-00041 part-00048 part-00055 part-00062 part-00069 part-00076 part-00083 part-00090 part-00097 part-00000 part-00007 part-00014 part-00021 part-00028 part-00035 part-00042 part-00049 part-00056 part-00063 part-00070 part-00077 part-00084 part-00091 part-00098 part-00001 part-00008 part-00015 part-00022 part-00029 part-00036 part-00043 part-00050 part-00057 part-00064 part-00071 part-00078 part-00085 part-00092 part-00099 part-00002 part-00009 part-00016 part-00023 part-00030 part-00037 part-00044 part-00051 part-00058 part-00065 part-00072 part-00079 part-00086 part-00093 reducer.rb part-00003 part-00010 part-00017 part-00024 part-00031 part-00038 part-00045 part-00052 part-00059 part-00066 part-00073 part-00080 part-00087 part-00094 part-00004 part-00011 part-00018 part-00025 part-00032 part-00039 part-00046 part-00053 part-00060 part-00067 part-00074 part-00081 part-00088 part-00095 part-00005 part-00012 part-00019 part-00026 part-00033 part-00040 part-00047 part-00054 part-00061 part-00068 part-00075 part-00082 part-00089 part-00096
こういう感じで、スタンドアローンな場合と複数台のサーバーで動かすときは大分やることが違ってくるので、わりとはまります。ということで、松本研のM1の人は自分がはまったところはblogとかにlogを書いて(ry。