各種バージョン
この記事の時点でのAmazon EMRは
Hadoop ディストリビューションは、Amazon 2.7.3となっていてhadoop 2.7.3で
アプリケーションは、Hive 2.1.1, Tez 0.8.4 なので極力これに近付ける
- MacOS Sierra 10.12.3
- Java 1.8
- hadoop 2.7.3
- hive 2.1.1
- mysql 5.5.49
EMRのバージョンと関連バージョンの確認はこちら
https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-release-components.html
インストール作業
1.java
# javaをインストール
$ brew cask install java
# JAVA_HOMEを設定
$ echo 'export JAVA_HOME=`/usr/libexec/java_home -v 1.8`' >> ~/.bash_profile
$ echo 'export PATH="PATH=$JAVA_HOME/bin:$PATH"' >> ~/.bash_profile
# バージョンを確認
$ java -version
java version "1.8.0_112"
Java(TM) SE Runtime Environment (build 1.8.0_112-b16)
Java HotSpot(TM) 64-Bit Server VM (build 25.112-b16, mixed mode)
2.mysql
# 既に入っていたら消す my.cnfとかも消す方が吉
$ brew uninstall mysql
# インストール
$ brew tap homebrew/versions
$ brew install mysql55
# パスを追加
$ echo 'export PATH="/usr/local/opt/mysql@5.5/bin:$PATH"' >> ~/.bash_profile
# mysql起動
$ brew services start mysql@5.5
# バージョンを確認
$ mysql -u root
Server version: 5.5.49 Homebrew
- ハマりポイント
# 5.5系でないと、hive 2.1.0のmetastoreの作成が、
# InnoDBでPK・Uniqueカラムのフィールド長の制限に引っ掛かる
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes
3.hadoop
# インストール
$ brew install hadoop
# 環境変数を設定
$ echo 'export HADOOP_HOME="/usr/local/Cellar/hadoop/2.7.3"' >> ~/.bash_profile
$ echo 'export HADOOP_CONF_DIR="$HADOOP_HOME/libexec/etc/hadoop"' >> ~/.bash_profile
# バージョンを確認
$ hadoop version
Hadoop 2.7.3
4.hive
# brewでは、2.1.0までしかないので、本家からダウンロードする
$ curl -O http://ftp.yz.yamagata-u.ac.jp/pub/network/apache/hive/hive-2.1.1/apache-hive-2.1.1-bin.tar.gz
# 解凍
$ tar xvzf apache-hive-2.1.1-bin.tar.gz
# インストール (今回わかりやすくするため、/usr/local/Cellar/hive/2.1.1へ配置)
$ sudo mv apache-hive-2.1.1-bin /usr/local/Cellar/hive/2.1.1
# 環境変数を設定
$ echo 'export HIVE_HOME="/usr/local/Cellar/hive/2.1.1"' >> ~/.bash_profile
$ echo 'export PATH="PATH=$HIVE_HOME/bin:$PATH"' >> ~/.bash_profile
# バージョンを確認
$ hive -H
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/usr/local/Cellar/hive/2.1.1/lib/log4j-slf4j-impl-2.4.1.jar!/org/slf4j/impl/StaticLoggerBinder.class]
-
homebrewで旧バージョンを使用する
https://qiita.com/cokaholic/items/6db92c23b43d18bdab82 -
ハマりポイント
2.1.1でないと、パーティショニング MSCK REPAIR TABLEがエラーになる。
ここまでで、インストールと環境設定が終わり、次は各種設定
設定作業
1.localhostへのssh接続できるようにする設定
Macの場合
システム環境設定 → 共有 から、「リモートログイン」にチェックを入れます。
以下のコマンドでauthorized_keysを追加します。
※まだ公開鍵を作成していない場合はssh-keygenで作成します。
$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
$ chmod 600 ~/.ssh/authorized_keys
以下のコマンドでlocalhostにsshで接続できることを確認します。
$ ssh localhost
2.HDFS設定
疑似分散モードでHDFSを構成します。
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://localhost:9000</value>
</property>
</configuration>
<configuration>
<property>
<name>dfs.name.dir</name>
<value>/var/lib/hdfs/name</value>
</property>
<property>
<name>dfs.data.dir</name>
<value>/var/lib/hdfs/data</value>
</property>
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
</configuration>
3.S3上のファイルへのアクセス設定
hadoopがS3にアクセス出来るようにします。
3.1.awsのjarにパスを通す
S3AFileSystemを使えるようにするため、「hadoop-aws-2.7.2.jar」にCLASSPATHを通します。
hadoop-env.shに以下を追記します。
export HADOOP_CLASSPATH=$HADOOP_CLASSPATH:$HADOOP_HOME/libexec/share/hadoop/tools/lib/*
3.2.S3AFileSystemとアクセスキーを設定
<configuration>
<property>
<name>fs.s3a.impl</name>
<value>org.apache.hadoop.fs.s3a.S3AFileSystem</value>
</property>
<property>
<name>fs.s3a.access.key</name>
<value>※ここにAWSのアクセスキー※</value>
</property>
<property>
<name>fs.s3a.secret.key</name>
<value>※ここにAWSのシークレットキー※</value>
</property>
</configuration>
4.mysqlをmetastore用のデータベースとして設定
4.1.データベースを作成
$ mysql -u root
# databaseのcharactersetはlaten1にしておく必要があります。
# 以下を参照
# http://tagomoris.hatenablog.com/entry/20110310/1299738606
mysql> create database metastore default character set 'latin1';
mysql> use metastore;
mysql> create user 'hive'@'localhost' identified by 'hive';
mysql> grant select, insert, update, delete, alter, create, index, references on metastore.* to 'hive'@'localhost';
4.2.jdbcドライバをhiveのライブラリへ追加
# ダウンロード
$ curl -O https://cdn.mysql.com//Downloads/Connector-J/mysql-connector-java-5.1.40.tar.gz
# 解凍
$ tar xvzf mysql-connector-java-5.1.40.tar.gz
# hiveのライブラリディレクトリに配置
$ mv mysql-connector-java-5.1.40/mysql-connector-java-5.1.40-bin.jar $HIVE_HOME/lib
4.3.mysqlのmetastoreデータベースをhadoopのメタストアとして使用するための設定
<configuration>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://localhost/metastore?useSSL=false</value>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>hive</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>hive</value>
</property>
<property>
<name>datanucleus.fixedDatastore</name>
<value>false</value>
</property>
<property>
<name>hive.exec.local.scratchdir</name>
<value>/tmp/hive</value>
</property>
<property>
<name>hive.downloaded.resources.dir</name>
<value>/tmp/hive</value>
</property>
<property>
<name>hive.querylog.location</name>
<value>/tmp/hive</value>
</property>
<!-- hiveでdynamodbを利用する場合の設定 -->
<property>
<name>dynamodb.endpoint</name>
<value>http://localhost:8000</value>
</property>
<property>
<name>dynamodb.awsAccessKeyId</name>
<value>hoge</value>
</property>
<property>
<name>dynamodb.awsSecretAccessKey</name>
<value>hogehoge</value>
</property>
</configuration>
4.4.metastoreの初期化
# schematoolで初期化を実行します。
$ schematool -dbType mysql -initSchema -verbose
5.HDFSのフォーマット
$ hdfs namenode -format
6.namenodeの起動とhdfsとS3への接続確認
以下のコマンドでHDFSを起動します。
YARN (Yet-Another-Resource-Negotiator)も起動したいので、 $HADOOP_HOME/sbin/start-all.sh
を実行する。
※停止する場合は $HADOOP_HOME/sbin/stop-all.sh
# パスワード聞かれたら、入力する
$ $HADOOP_HOME/sbin/start-all.sh
# hdfsへの接続確認(この時点では、まだHDFS上にファイルが無いので一覧には何も表示されません。)
$ hadoop fs -ls /
# s3のバケットが見れるかも確認
$ hadoop fs -ls s3a://※ここにS3のbucket名※/
お疲れ様です。
ここまでで、各種設定が終わりました。
次は、S3上に配置したTSVファイルに対してhiveでクエリを投げてみます。
S3上に配置したTSVファイルに対してhiveでクエリを投げてみます!
1.S3バケットの状態
# S3バケットには、カレンダーマスターを年でパーティショニングした状態で、TSVファイルを置いてある
$ hadoop fs -ls s3a://hivelocal/input/calendar_master/
Found 2 items
drwxrwxrwx - 0 1970-01-01 09:00 s3a://hivelocal/input/calendar_master/year=2016
drwxrwxrwx - 0 1970-01-01 09:00 s3a://hivelocal/input/calendar_master/year=2017
# こんな感じ
$ hadoop fs -ls s3a://hivelocal/input/calendar_master/year=2016/
Found 1 items
-rw-rw-rw- 1 5855 2017-02-19 14:06 s3a://hivelocal/input/calendar_master/year=2016/calendar_master.csv
$ hadoop fs -ls s3a://hivelocal/input/calendar_master/year=2017/
Found 1 items
-rw-rw-rw- 1 5840 2017-02-19 14:06 s3a://hivelocal/input/calendar_master/year=2017/calendar_master.csv
2.hiveQLを準備
データベース作って、テーブル作って、ロードして、パーティショニングするスクリプト
-- データベースを作成
CREATE DATABASE IF NOT EXISTS HIVE_TEST;
USE HIVE_TEST;
-- カレンダーマスタテーブルを削除
DROP TABLE IF EXISTS calendar_master;
-- カレンダーマスタテーブルを作成
CREATE EXTERNAL TABLE IF NOT EXISTS calendar_master (
dt date, -- 日付
yobi tinyint, -- 曜日
shukujitsu_code tinyint -- 祝日コード
)
PARTITIONED BY (`year` string)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
LINES TERMINATED BY '\n'
STORED AS TEXTFILE
LOCATION '${INPUT}/calendar_master/';
-- テーブルにすべてのパーティションを挿入
MSCK REPAIR TABLE calendar_master;
3.テスト用のシェルを用意
# !/bin/sh
# hiveコマンドのオプション debug
OPTS=-v
# hiveQLソースがあるフォルダ
SRC=./src/hive
# INPUTデータがある、S3バケット指定
INPUT=s3a://hivelocal/input
# OUTPUTデータの出力先S3バケット指定
OUTPUT=s3a://hivelocal/output
hive $OPTS -f $SRC/create_calendar_master.q -dINPUT=$INPUT || { echo oops!; exit 1; }
4.いざ実行!
$ sh test.sh
CREATE DATABASE IF NOT EXISTS HIVE_TEST
OK
Time taken: 1.738 seconds
USE HIVE_TEST
OK
Time taken: 0.019 seconds
DROP TABLE IF EXISTS calendar_master
OK
Time taken: 0.127 seconds
CREATE EXTERNAL TABLE IF NOT EXISTS calendar_master (
dt date, -- 日付
yobi tinyint, -- 曜日
shukujitsu_code tinyint -- 祝日コード
)
PARTITIONED BY (`year` string)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
LINES TERMINATED BY '\n'
STORED AS TEXTFILE
LOCATION '${INPUT}/calendar_master/'
OK
Time taken: 1.667 seconds
MSCK REPAIR TABLE calendar_master
OK
Partitions not in metastore: calendar_master:year=2016 calendar_master:year=2017
Repair: Added partition to metastore calendar_master:year=2016
Repair: Added partition to metastore calendar_master:year=2017
Time taken: 3.469 seconds, Fetched: 3 row(s)
お! Partitionも作られてるね〜イイね!
5.確認してみる
$ hive
# データベースあった!
hive> use HIVE_TEST;
OK
Time taken: 1.254 seconds
# テーブルもあった!
hive> show tables;
OK
calendar_master
Time taken: 0.283 seconds, Fetched: 1 row(s)
# パーティションもあった!
hive> show partitions calendar_master;
OK
year=2016
year=2017
Time taken: 0.266 seconds, Fetched: 2 row(s)
# TSVのデータも取り込まれている!
hive> select * from calendar_master;
OK
2016-01-01 6 1 2016
2016-01-02 7 0 2016
2016-01-03 1 0 2016
2016-01-04 2 0 2016
2016-01-05 3 0 2016
〜省略
2016-12-30 6 0 2016
2016-12-31 7 0 2016
2017-01-01 1 1 2017
2017-01-02 2 9 2017
2017-01-03 3 0 2017
2017-01-04 4 0 2017
2017-01-05 5 0 2017
Time taken: 0.251 seconds, Fetched: 731 row(s)
hive>
やった〜!
お次は、S3上に出力できるか試せたら、追記します。
終わりに
hadoop,hiveは、構成がいろいろ出てて、初心者にはかなりハードル高い感じでした。
CDH? EMR なんだかんだ・・・
docker使えば一発じゃんとかあるかもしれませんが
今回は、理解を進める上でも、オールインワンは使わずやってみました。