2013年10月1日火曜日
HadoopでHDFS化したログをHiveとImpalaで高速検索
◆ 目的
HadoopでHDFSを組んだ環境に、HiveとImpalaを導入し、
高速ログ検索を実現させる。
Hdoop、Hive、Impalaの設定はすべて終わっており、
利用できる状態にあるものとする。
ここではどのようにログを取り込み、
検索を実施するのか一通りの手順を記載する。
Hadoop、Hiveは耳にしたことがあっても、
まだImpalaについては知らないという人もいるだろうか。
Impalaについてのまとまった記事
◆ 環境
説明するための環境を定義しておく。
・ログの収集対象であるアプリケーションサーバ名
app1
app2
app3
・上記アプリケーションサーバのログ出力形式
ホスト名と日時が付与され、1時間おきにローテートされる。
app_app1_2013100100.log.gz ←app1の2013年10月01日00時ログ
app_app1_2013100101.log.gz ←app1の2013年10月01日01時ログ
app_app1_2013100102.log.gz ←app1の2013年10月01日02時ログ
app_app2_2013100100.log.gz
app_app2_2013100101.log.gz
app_app2_2013100102.log.gz
app_app3_2013100100.log.gz
app_app3_2013100101.log.gz
app_app3_2013100102.log.gz
・ログ収集サーバ
log1サーバ
log2サーバ
log3サーバ
・
・
・
何台いてもいいのだが、これらサーバ群の特定領域をHDFS化させている。
HDFS領域
/log/
そしてこのサーバ上でHiveとImpalaを動作させている。
appサーバ群のログを取得する際の一時的な保管場所は以下をする。
HDFS化していないローカルディスク(log1にあるとする)である。
/tmp/log/
◆ ログ投入事前作業
・テーブル作成
logサーバ群上でテーブルを作成する。
当然テーブルを作成するのは最初だけである。
どういったログ検索を事前に行うか決まっていないため、
柔軟性を優先し、ログはそのままmsgというカラムに入れる。
パーティションとして日時を付与する。dtと名称する。
logサーバ群のマスタ上で実行する。
$ sudo -u hdfs hive
> CREATE TABLE app_log (msg STRING) PARTITIONED BY (dt STRING) ROW FORMAT DELIMITED LINES TERMINATED BY '\n';
> CREATE TABLE app_impala (msg STRING) PARTITIONED BY (dt STRING) ROW FORMAT DELIMITED LINES TERMINATED BY '\n' STORED AS SEQUENCEFILE;
・テーブルの確認
> SHOW TABLES;
log
log_impala
> DESC app_log;
msg string
dt string
> DESC app_log_impala;
msg string
dt string
◆ ローカルディレクトリへのログ収集
まずはlogサーバのローカルディスクである/tmp/log/へ
appサーバ群のログを持ってくる。
scpなりで定期的にバッチ処理させればよい。
expectを利用してscpを自動化
sshで多段接続をしてscp
◆ HDFSへのログ投入
ローカルディスクである/tmp/log/からログをHDFSへ取り込む。
時間ごとのログ単位でパーティションを切っていく。
・HDFS化
(2013年10月01日00時のログを投入する場合の実行例)
% sudo -u hdfs /usr/bin/hive -e "LOAD DATA LOCAL INPATH '/tmp/log/*2013100100*' \
INTO TABLE app_log PARTITION (dt='2013100100')"
(2013年10月01日01時のログを投入する場合の実行例)
% sudo -u hdfs /usr/bin/hive -e "LOAD DATA LOCAL INPATH '/tmp/log/*2013100101*' \
INTO TABLE app_log PARTITION (dt='2013100101')"
(2013年10月01日02時のログを投入する場合の実行例)
% sudo -u hdfs /usr/bin/hive -e "LOAD DATA LOCAL INPATH '/tmp/log/*2013100102*' \
INTO TABLE app_log PARTITION (dt='2013100102')"
※取り込み元のローカルパス名に''必須
・パーティションの設定の確認
$ sudo -u hdfs hive
> SHOW PARTITIONS app_log;
dt=2013100100
dt=2013100101
dt=2013100102
・ファイルが取り込まれたことの確認
% hdfs dfs -ls -R /log/app_log/
/log/app_log/dt=2013100100/app_app1_2013100100.log.gz
/log/app_log/dt=2013100101/app_app1_2013100101.log.gz
/log/app_log/dt=2013100102/app_app1_2013100102.log.gz
/log/app_log/dt=2013100100/app_app2_2013100100.log.gz
/log/app_log/dt=2013100101/app_app2_2013100101.log.gz
/log/app_log/dt=2013100102/app_app2_2013100102.log.gz
/log/app_log/dt=2013100100/app_app3_2013100100.log.gz
/log/app_log/dt=2013100101/app_app3_2013100101.log.gz
/log/app_log/dt=2013100102/app_app3_2013100102.log.gz
◆ Impalaへのログ投入
HDFSにログが格納された。
それをHive経由で取得し、Impalaのテーブルに入れ込む。
・Impalaへの取り込み
(2013年10月01日00時のログを投入する場合の実行例)
sudo -u hdfs /usr/bin/hive -hiveconf hive.exec.compress.output=true \
-hiveconf hive.stats.autogather=false \
-hiveconf mapred.max.split.size=256000000 \
-hiveconf mapred.output.compression.type=BLOCK \
-hiveconf mapred.output.compression.codec=org.apache.hadoop.io.compress.SnappyCodec \
-e "INSERT INTO TABLE app_log_impala PARTITION (dt='20131000') \
SELECT msg FROM app_log where dt='2013100100'"
※オプションは各環境ごとに変えればよい。
(2013年10月01日01時のログを投入する場合の実行例)
sudo -u hdfs /usr/bin/hive -hiveconf hive.exec.compress.output=true \
-hiveconf hive.stats.autogather=false \
-hiveconf mapred.max.split.size=256000000 \
-hiveconf mapred.output.compression.type=BLOCK \
-hiveconf mapred.output.compression.codec=org.apache.hadoop.io.compress.SnappyCodec \
-e "INSERT INTO TABLE app_log_impala PARTITION (dt='2013100101') \
SELECT msg FROM app_log where dt='2013100101'"
(2013年10月01日02時のログを投入する場合の実行例)
sudo -u hdfs /usr/bin/hive -hiveconf hive.exec.compress.output=true \
-hiveconf hive.stats.autogather=false \
-hiveconf mapred.max.split.size=256000000 \
-hiveconf mapred.output.compression.type=BLOCK \
-hiveconf mapred.output.compression.codec=org.apache.hadoop.io.compress.SnappyCodec \
-e "INSERT INTO TABLE app_log_impala PARTITION (dt='2013100102') \
SELECT msg FROM app_log where dt='2013100102'"
・ファイルが取り込まれたことの確認
% hdfs dfs -ls -R /log/app_log_impala/
◆ 削除処理
ログを削除する手順も残しておく。
・パーティションごと削除する場合
% sudo -u hdfs /usr/bin/hive -e "ALTER TABLE app_log DROP PARTITION (dt='2013100100')"
% sudo -u hdfs /usr/bin/hive -e "ALTER TABLE app_log DROP PARTITION (dt='2013100101')"
% sudo -u hdfs /usr/bin/hive -e "ALTER TABLE app_log DROP PARTITION (dt='2013100102')"
% sudo -u hdfs /usr/bin/hive -e "ALTER TABLE app_log_impala DROP PARTITION (dt='2013100100')"
% sudo -u hdfs /usr/bin/hive -e "ALTER TABLE app_log_impala DROP PARTITION (dt='2013100101')"
% sudo -u hdfs /usr/bin/hive -e "ALTER TABLE app_log_impala DROP PARTITION (dt='2013100102')"
・テーブルごと削除する場合
% sudo -u hdfs /usr/bin/hive -e "DROP TABLE log"
% sudo -u hdfs /usr/bin/hive -e "DROP TABLE log_impala"
◆ 検索
・Hiveでの検索例
% sudo -u hdfs hive
> SELECT msg FROM app_log WHERE dt='2013100100' AND msg LIKE '%hoge%';
> SELECT msg FROM app_log WHERE dt REGEXP '2013100[012]' AND msg LIKE '%hoge%' AND msg LIKE '%piyo%';
シェルモードに入らない場合は-eオプションを使う。
% sudo -u hdfs hive -e "SELECT ~"
・停止処理
検索処理実行後Killコマンドが発行される。
Ctrl+Cで抜けただけではバックエンドで検索が続けられるため、
提示されたこのコマンドで停止させること。
Kill Command = $HADOOP_PATH/bin/hadoop job -kill job_201310012000_0001
・Impalaでの検索
% sudo -u hdfs -i impala-shell -r
> SELECT ~
検索対象テーブルとしてapp_log_impalaを指定する以外はhiveと違いはない。
-rオプションを付与しないとメタデータがずっとキャッシュされる
シェルモードに入らない場合は-qオプションを使う。
% /usr/bin/impala-shell -i -r -q "SELECT ~"
オプションの詳細参照
Hiveと違ってImpalaはctrl+cで抜ければ全ノードのimpalad処理が停止する