ビッグデータ取り扱いまでの流れ2 解析編
今回は収集したデータをどう解析していくか書いていきます。
解析にはHadoopを利用します。
Hadoopの動作環境はAmazon EMR (Elastic MapReduce)を使います。
- fluentdのインストール
- td-loggerでアプリケーションログの吐き出し
- td-loggerで受け取ったログをS3に送信
- S3のデータをHadoopで解析
- Hadoopで解析したデータをRDSに突っ込む
今回は前回の続きということでS3のデータをHadoopで解析から解説します。
Hadoopの処理はSQLライクに書けるHiveを利用します。
S3のデータをHadoopで解析
先程も書きましたが、EMRを利用します。
基本的にはコマンドラインのみでやっていきます。
なのでコマンドラインツールを予めインストールしといてください。
参考図書はこちら
- 作者: 佐々木達也
- 出版社/メーカー: 秀和システム
- 発売日: 2012/09
- メディア: 単行本
- クリック: 14回
- この商品を含むブログ (4件) を見る
EMRの起動
まずはEMRの起動から
認証系の設定ファイルを書きます
.credentials.jsonをホームディレクトリに追加。内容は以下です
{ "access-id": 'AWSのkey', "private-key": 'AWSのsecret-key', "key-pair": '公開鍵のファイル', "key-pair-file": '公開鍵のファイルのパス', 'region': 'リージョン名[ap-northeast-1(東京)]', "log-uri": '' }
第3回 Amazon Elastic MapReduce Ruby ClientでEMRを起動する:Amazon Elastic MapReduceの使い方─Hadoopより手軽にはじめる大規模計算|gihyo.jp … 技術評論社
こちらが参考になります。
起動コマンドはこちら
elastic-mapreduce --create --alive --name "クラスター名" --key-pair "キーの名前" ¥ --instance-group master --instance-type m1.small --instance-count 1 ¥ --bid-price 0.02 ¥ --instance-group core --instance-type m1.small --instance-count 2 ¥ --bid-price 0.02 ¥ --hive-interactive
これで起動が完了です。
解説すると
--create で起動 --alive でシャットダウンを手動で行う設定 --name Hadoopクラスター名を指定 --key-pair インスタンスの鍵を指定 --instance-group master 詳しくは解説しませんが、hadoopにはmaster, core, taskのインスタンスグループがあります。masterとcoreは必ず必要です。 --instance-type インスタンスのサイズなどを指定します --instance-count そのグループのインスタンス数を指定。masterは1つ。 --bid-price スポットインスタンスの入札価格 --hive-interactive hiveを使うためのオプション。これがないとhiveが使えません。
スポットインスタンスに関して詳しくはこちら(
Amazon EC2 スポットインスタンス - Amazon EC2 (クラウド上の仮想サーバー Amazon Elastic Compute Cloud) | アマゾン ウェブ サービス(AWS 日本語))
確認は
elastic-mapreduce --list --active
としたとき
j-[jobflow_id] WAITING [public DNS][クラスター名] COMPLETED Setup Hive
このように
WAITING
と
COMPLETED
と表示されていれば利用できます。
hiveの利用
sshでmasterノードに入り作業をします
ssh -i [公開鍵のパス] hadoop@[public DNS]
ユーザーはhadoopユーザーを利用します。
sshでログイン後
hive
と入力します。するとhiveのコンソールが表示されます。
まずはS3からデータを取り込みます。(厳密には取り込むっていい方は違うっぽい(もうちょい詳しくなりたい))
イメージ的にはテーブルを作ってそこにS3のデータを取り込む
この辺はこちらを参考にしました。
はじめてのEMR/fluentdでS3にアップロードしたログをElastic MapReduceで検索・集計する | Developers.IO
CREATE EXTERNAL TABLE IF NOT EXISTS [テーブル名] (dt string, tag string, json string) PARTITIONED BY ( PT STRING ) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n'
このようなテーブルを作成します。
desc [テーブル名]
とすると
dt string tag string json string pt string
このようなcolumn情報が表示されます。
前回の記事からログは
2014-03-29T00:40:11+09:00 my_app.test {"hoge":"piyo"}
このような感じになります。
なのでイメージ的には
dt 2014-03-29T00:40:11+09:00
tag my_app.test
json {"hoge" : "piyo"}
というデータが入っていきます。
ただこの段階ではソースは指定されていません。
ソースの指定はパーティションの追加により行います。
パーティションの追加は
ALTER TABLE [テーブル名] ADD IF NOT EXISTS PARTITION (pt = '[日付情報など]') LOCATION 's3://[S3のバケット名]'
このように行います。
ここまででhiveでS3に保存したデータを取り扱うことができます。
実際にSELECT文で色々試してみましょう
select * from [テーブル名];
とすると仮にS3の内容が
2014-03-29T00:40:11+09:00 my_app.test {"hoge":"piyo"} 2014-03-29T00:40:11+09:00 my_app.test {"hoge":"fuga"}
だとすると
そのまま
2014-03-29T00:40:11+09:00 my_app.test {"hoge":"piyo"} 2014-03-29T00:40:12+09:00 my_app.test {"hoge":"fuga"}
と出てきます。
jsonが少々扱いにくいのでこのように書くとjsonの中身を利用できます。
select hoge from [テーブル名] LATERAL VIEW json_tuple(テーブル名.json, hoge) j AS hoge
とすると
piyo fuga
となります。
さらに条件もjsonの中身のやつを利用できます
select hoge from [テーブル名] LATERAL VIEW json_tuple(テーブル名.json, hoge) j AS hoge where hoge = "piyo"
とすると
piyo
のみが取り出せます。
前回のと組み合わせるとアプリケーションログを取得し、かつhiveにより利用出来るようになりました。
今回はボリュームが多くなってきたので、この辺で。
次回はこれらの処理をrubyから動作させる方法について書いていきたいと思います。
参考図書
この本は本当に参考になりました。まず最初に読むべき本かと思います。
- 作者: 佐々木達也
- 出版社/メーカー: 秀和システム
- 発売日: 2012/09
- メディア: 単行本
- クリック: 14回
- この商品を含むブログ (4件) を見る
ビッグデータ取り扱いまでの流れ1 収集編
最近ビッグデータを取り扱ってきているので、その流れを記録しようかと思います。
Ruby on Railsで構築していますが、一部以外は別の言語やフレームワークでも利用できます。
ビッグデータの定義ですが、この本の帯の「データサイズが悩みの種ならそれはもうビッグデータです」
- 作者: 佐々木達也
- 出版社/メーカー: 秀和システム
- 発売日: 2012/09
- メディア: 単行本
- クリック: 14回
- この商品を含むブログ (4件) を見る
っていうのがすごくしっくりきました。
丁度データサイズに悩み始めてきたため、ビッグデータを取り扱っているといえるでしょう。
ざっくりとした流れは
- fluentdのインストール
- td-loggerでアプリケーションログの吐き出し
- td-loggerで受け取ったログをS3に送信
- S3のデータをHadoopで解析
- Hadoopで解析したデータをRDSに突っ込む
というような流れとなっております。
fluentdのインストール
これはいろんなところで書いてあるのであまり深くは書きませんが、
こんな感じでインストールします。
/etc/yum.repos.d/td.repo
[treasuredata] name=TreasureData baseurl=http://packages.treasure-data.com/redhat/$basearch gpgcheck=0
$ yum update $ yum install td-agent
td-loggerでアプリケーションログの吐き出し
Gemfileにて
gem 'td-logger'
を追加しbundle install
ファイル
config/treasure_data.yml
development: agent: localhost:24224 tag: アプリケーション名 debug_mode: true # enable debug mode production: agent: localhost:24224 tag: アプリケーション名 debug_mode: false # disable logging test:
を追加
取得したい場所に
TD.event.post('[タグの名前]', ハッシュ)
するとログでは
datetime アプリケーション名.タグの名前 json
みたいな感じです。具体的に入れると
TD.event.post('test', { hoge: :piyo })
アプリケーション名をmy_appとするとログは
2014-03-29T00:40:11+09:00 my_app.test {"hoge":"piyo"}
みたいな感じになります。
td-loggerで受け取ったログをS3に送信
次は
2014-03-29T00:40:11+09:00 my_app.test {"hoge":"piyo"}
こちらのログをS3に入れます。
設定ファイルに次の設定を追加します
/etc/td-agent/td-agent.conf
<match my_app.event> type s3 aws_key_id AWSのキー aws_sec_key AWSのシークレットキー s3_bucket バケット名 s3_endpoint S3のリージョン.amazonaws.com s3_object_key_format %{path}%{time_slice}_%{index}_%{hostname}.%{file_extension} path events/ buffer_path /var/log/fluentd/events_s3 time_slice_format %Y-%m-%d/%H time_slice_wait 10m </match>
これでオッケー。
あとはしばらく動かして、バケットの中身を見ると、gzip形式のファイルがどんどん溜まっていきます。
それをhadoopで処理します。
動いてないと思ったら
tail -f /var/log/td-agent/td-agent
などでログを見て行きましょう。
というわけで今回はここまで。
次回はhadoopで処理する方法を書いていきます。
参考記事
fluentd+rails+mongoでサクッとログ環境を整備してみる - dev.log
データサイエンティスト養成読本 [ビッグデータ時代のビジネスを支えるデータ分析力が身につく! ] (Software Design plus)
- 作者: 佐藤洋行,原田博植,下田倫大,大成弘子,奥野晃裕,中川帝人,橋本武彦,里洋平,和田計也,早川敦士,倉橋一成
- 出版社/メーカー: 技術評論社
- 発売日: 2013/08/08
- メディア: 大型本
- この商品を含むブログ (12件) を見る
相対性理論とアジャイル開発の関係
今回はディレクター向けにアジャイル開発の難しい点を(特殊)相対性理論を用いて解説したいと思います。
おそらくタイトルの段階でどちらも理解している方は内容が想像つくのではないのでしょうか。
相対性理論について
もうこの名前だけでわけわからんって方が多いかと思いますが、一言で相対性理論を表すと
「光速は不変」
とにかくこれだけ抑えておけばこれから話す内容も理解できるかと。
これから、光速は不変ということをもう少し詳しく説明しますが、
その前に不変じゃない普通の速度について説明します。
まずある人Aが時速5kmで歩いているとします。
Aは電車の中にいて、この電車は時速80kmで動いているとします。
すると電車の外にいる人からするとAは時速85kmで動いている状態となります。
これが普通です。
次にAが光だったとします。
光なので光の速度 c で動きます。
光は電車の中にいて、この電車は時速80kmで動いているとします。
すると光は時速 c + 80 kmになるでしょうか。
答えはなりません。
理由はよくわかりませんが、これこそが相対性理論の光速不変たる所以です。
次にもう一度電車の例で例えます。
レーザー光を電車の床から天井に向けて照射したとします。
電車の中から見ている人のイメージはこちら
電車が動いていると外から見ている人には光はこう見えます
光の部分だけ取り出すと
こんな感じになります。
長さ(移動距離)は速度 x 時間なので
光速 x 時間 が光の長さになります。
さて、この時光の長さが変わっているかと思います。
長い方を L1
短い方を L2
しかし光速は先ほど説明したように不変で c と定義します。
すると
L1 = c x 時間1
L2 = c x 時間2
となります。
L1 != L2 なので 時間1 != 時間2 です。
「あれ? 時間が違うってどういうこと?」
と思いますよね?
そのままの意味で、光速で動くものは動いていないものと比較し時間の進み方が違います。
つまり相対性理論を考えるとこの世で絶対的なものは光速であり、空間と時間は相対的だということです。
ちなみにこの理論を駆使すると速度と関係のある F=maや E = 1/2 mv^2なんかの速度以外が全て相対的になるため、速度が光速に近づくものは質量が無限に近づきます。
では次にアジャイル開発の話
アジャイル開発におけるスコープ
スコープは簡単にいうと機能です。あるプロジェクトにおいてプロジェクトを進めるにあたって考えなければいけないものが、
- スコープ
- リソース
- 納期・リリース日
の3つがあります。
あるプロジェクトで実際に開発したことがある方はわかるかもしれませんが、
- リソース
- 納期・リリース日
は絶対的なものです。
リソースは減ることはあっても増えることはめったにありません。
納期・リリース日も特に受託の場合なんかは絶対に遅らせることは出来ません。
とすると、確実にスコープが揺らぐものとなります。
無理やり式に直すと
リリース日 - 現在の日 = スコープ x リソース
絶対的なリリース日とリソース、相対的なスコープという関係性が見えてくるかと思います。
2つの関係
ここまで見ていくと
- 絶対的なもの
- 相対的なもの
という2つのキーワードがあり
対応させると
光速 <=> リリース日、リソース
時間・空間 <=> スコープ
このような関係性が見えてきます。
ではこの関係性をどう活かしていこうかということですが、
これまで見てきたように光速は不変なものというのは物理学的に変わらない事実です。
そしてプロジェクトにおいてもリリース日、リソースは不変です。
つまりプロジェクトを成功させるにはいかにスコープを揺らがせてもいいかにかかっています。
設計の段階でスコープを不変のものにしてしまうとそのプロジェクトは絶対に炎上します。
スコープを変動させてプロジェクトがうまくいくようにどうディレクションしていくか。
これこそがアジャイル開発では重要なことです。
まとめ
特に構成も考えず書いていたら、相対性理論の説明いらなくね?みたいな記事になりました。
プロジェクトでも不要なスコープをどんどん削っていくことが重要ですね!
あとアジャイル開発においてリリース日を変動させる裏技も書いております。
詳しくはこちらの本を参考に!
- 作者: Jonathan Rasmusson,西村直人,角谷信太郎,近藤修平,角掛拓未
- 出版社/メーカー: オーム社
- 発売日: 2011/07/16
- メディア: 単行本(ソフトカバー)
- 購入: 42人 クリック: 1,991回
- この商品を含むブログ (245件) を見る
- アーティスト: 相対性理論
- 出版社/メーカー: commmons
- 発売日: 2011/04/27
- メディア: CD
- 購入: 7人 クリック: 590回
- この商品を含むブログ (107件) を見る
MVCモデルで見るRubyとPHPの違い
約1年くらいPHPを触っていないのでもしかしたら的はずれなことを言ってしまうかもしれませんが、MVCモデルを例にとってRubyとPHPの違いを自分なりに考えてみたいと思います。
自分が利用したことのあるフレームワーク
Ruby -> Rails
PHP -> CodeIgniter
なのでここから見ていきます。
ちなみにこれからダラダラと書きますが、結論は(個人的に)Rubyの方が優れているという内容を書きます。
MVCモデルについて、詳しく説明することもないのですが、RailsとCodeIgniterで大きく違う点を示したいと思います。
まずはCodeIgniterのMVCモデルから
このようになっております。
つまりRubyは全てのものがオブジェクトであるという点からPHPとはMVCの概念も異なるということが言えます。
仮にとあるWebサービスのユーザーランキングページを作るとします。
そのページにはユーザーのランキング情報プラス各ユーザーの詳細情報も見ることができます。
CodeIgniterではまずモデルにランキング情報を取得するメソッドを作成します。
同様にモデルにユーザーの詳細情報を取得するメソッドも作成します。
コントローラーでランキング情報を取得するメソッドを呼び出し、
結果をループさせユーザーの詳細情報が付与されたランキング情報のハッシュを作成します。
そのハッシュをviewに渡しforeachで表示させます。
イメージ的には
<?php //モデル function ranking{ ~ // {"rank" => , "user_id" => } return ranking_hash; } function user_info($user_id){ ~ // {"id" => , "name" => } return user_info_hash; } ?> <?php //コントローラー $ranking = $this->モデル->ranking; foreach($ranking as $user){ $user_data = $this->モデル->user_info($user["user_id"]); $ranking_array = { "rank" => $user["rank"], "user" => $user_data } } ?> //ビュー <?php foreach($ranking_array as $user): ?> <tr> <td><?php echo $user["rank"]; ?></td> <td><?php echo $user["user"]["name"]; ?></td> </tr> <?php endforeach; ?>
このような感じかと思います。
一方Railsで同様のことをすると
コントローラーでモデルのランキングメソッドを呼び出す
ビューでモデルの詳細メソッドを呼び出す
このようになります。
#モデル def self.ranking ~ ranking_object end def user_name self.name end #コントローラー @ranking = モデル.ranking #ビュー <% @ranking.each do |rank, user| %> <tr> <td><%= rank %></td> <td><%= user.user_name %></td> </tr> <% end %>
このような感じになります。CodeIgniterと比べるとコントローラーのやることがかなり減るかと思います。
また、そもそもコントローラーで@rankingとしなくても、ビュー側で
<% モデル.ranking.each do |rank, user| %>
というようにも書くことが出来ます。
ただこれは一長一短でもあり、ビューにプログラミング要素を入れ過ぎないようにすることも必要です。
メリット・デメリットを整理すると
メリット | デメリット | |
CodeIgniter | ビューのロジックが減るためデザイナーが扱いやすい | コントローラーが肥大化する |
Rails | コントローラーがスッキリする | デザイナーにもオブジェクト指向を理解してもらう必要がある |
あとは色々パターンがあるためRailsの場合はチューニングがめんどくさそうです。
CodeIgniterの場合はコントローラーのベンチマークをとってチューニングするだけで良さそうですが。
まとめですが、個人的にはコントローラーがスッキリするRailsの方が好きだし優れていると感じます!
駆け足気味でしたが、MVCモデルを例にとってRubyとPHPの違いを示してみました。
これから新たな言語を学ぶ方や、PHPをずっとやっている方はRubyを使ってみてはいかがでしょうか?
ちなみにずっとPHPをやっていた方は最初はコントローラーが長くなるかと思いますが、徐々に慣れていきスッキリとしたコントローラーになるでしょう。
Ruby on Rails 3 アプリケーションプログラミング
- 作者: 山田祥寛
- 出版社/メーカー: 技術評論社
- 発売日: 2011/05/12
- メディア: 大型本
- 購入: 27人 クリック: 664回
- この商品を含むブログ (41件) を見る
- 作者: 黒田努
- 出版社/メーカー: インプレスジャパン
- 発売日: 2013/03/22
- メディア: 単行本(ソフトカバー)
- クリック: 3回
- この商品を含むブログ (6件) を見る
Rails初心者から中級者になったと感じたきっかけ
エンジニア(プログラマー)をやっていると基本的には徐々にレベルアップしていきます。
しかしある点で閾値を越えて、レベルが一気に上がると感じる瞬間があります。
皆さんどうでしょうか?
自分の場合は
クラスメソッドとインスタンスメソッドの違いをはっきり理解したことがそのきっかけでした。
これまでぼんやりとモデルにメソッドを追加していたものがかなり自信を持ってメソッドを追加出来るようになりました。
今回はクラスメソッドとインスタンスメソッドの違いを簡単に紹介して、他にも初級者から中級者に上がるようなパターンを考えてみたいと思います。
クラスメソッドとインスタンスメソッドの違い
本当にその名の通りなんですが、
クラス全体で使えるのがクラスメソッド
あるクラスのインスタンスで使えるのがインスタンスメソッド
具体例を書くと、rubyでは
class Dog #クラスメソッド def self.choge end #インスタンスメソッド def ihoge end end
このように書きます。とりあえずクラスはDog(犬)です。
クラスメソッドは self.メソッド名 という書き方をします。
メソッド内のselfの違い
これはこちらの記事が参考になります。
インスタンスメソッド内での self の値を調べた - (゚∀゚)o彡 sasata299's blog
クラスメソッド内ではオブジェクト、インスタンスメソッド内ではインスタンスとなります。
(解説していけば解説していくほどそのまんまだな)
呼び出し方の違い
呼び出し方は
#クラスメソッド Dog.choge #インスタンスメソッド dog = Dog.new dog.ihoge
のようになります。クラスメソッドはクラスからそのまま呼び出し、インスタンスメソッドはクラスのインスタンスから呼び出します。
使い方の違い
ここがある意味今回の記事一番のポイントかと思います。
説明するとこれまで同様、そのまんまの説明になるので、上記のDogを利用した具体例から。
クラスメソッドの場合
- Dogのうち一番年齢の高いDogを取り出すメソッド
- Dogのうちオスのみを取り出すメソッド
例えばこんな感じ
class Dog < ActiveRecord::Base # 一番年齢の高いDog def self.get_oldest self.order("age DESC").limit(1) end # オスのみを取り出す def self.get_male self.where(:sex => "male") end end
要は「クラス全体の中から何かを取り出す」場合などに利用されます。
インスタンスメソッドの場合
- とあるDogの年齢、性別をHashで取り出すメソッド
- とあるDogの親のDogを取り出すメソッド(親が子のIDを持っているケース)
class Dog < ActiveRecord::Base # 年齢、性別 def get_profile { :age => self.age, :sex => self.sex } end # 親を取り出す def get_parent Dog.where(:child => self.id) end end
こちらは「あるインスタンスの何かを取り出す」場合などに利用されます。インスタンスメソッドの場合は更新系もよく出てくるかと思います。
とりあえずここまででクラスメソッドとインスタンスメソッドの違いはなんとなくわかっていただけたかと。