Digdag+Embulkで発生したエラーと対策

2016.12.20

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

EC2にDigdagとEmbulkをインストールした環境にMacからssh接続して実行していると複数のエラーが発生しました。
それらの対応策を備忘録として書いていきます。

環境

Mac OSX 10.9.5 Amazon EC2 Amazon Linux
Digdag 0.8.13
Embulk 0.8.13

目的

S3に配置してあるGZIP圧縮されたTSVファイル(ヘッダー無し)をRedshiftにロードする。
DigdagとEmbulkの実行はEC2インスタンス上。

実行時の状態

Digdag実行ファイル

Digdagで実行する処理内容をYAMLで記述しています。
guessで「guess-redshift-output.yml」を読込み、追記修正したものを「config-redshift-output.yml」に上書き保存し、Embulkで読込んでいます。

timezone: UTC
 
+guess:
  sh>: embulk guess embulk/guess-redshift-output.yml -o embulk/config-redshift-output.yml
 
+load:
  embulk>: embulk/config-redshift-output.yml

設定ファイル: guess-redshift-output.yml

こちらもYAMLでS3とRedshiftの接続情報を記述。

in:
  type: s3
  bucket: S3のバケット名
  path_prefix: S3内の対象ファイル名(プレフィックスで読込み可能)
  endpoint: s3-ap-northeast-1.amazonaws.com
  access_key_id: XXXXX
  secret_access_key: XXXXX
out:
  type: redshift
  host: Redshiftのエンドポイント
  user: Redshiftのマスターユーザー名
  password: Redshiftのマスターパスワード
  database: データベース名
  schema: スキーマ名
  table: テーブル名
  access_key_id: XXXXX
  secret_access_key: XXXXX
  iam_user_name: XXXXX
  s3_bucket: S3バケット名
  s3_key_prefix: temp/redshift
  mode: insert

実行

Digdagの実行

$ digdag run 実行ファイル名

実行結果

Redshiftにロードが完了すれば下記のログが最後に表示されます。

Success. Task state is saved at .digdag/status/20161130T000000+0000 directory.
  * Use --session <daily | hourly | "yyyy-MM-dd[ HH:mm:ss]"> to not reuse the last session time.
  * Use --rerun, --start +NAME, or --goal +NAME argument to rerun skipped tasks.

失敗した場合はこんな表示です。

error: 
  * +csack+load:
    Command failed with code 1

Task state is saved at .digdag/status/20161130T000000+0000 directory.
  * Use --session <daily | hourly | "yyyy-MM-dd[ HH:mm:ss]"> to not reuse the last session time.
  * Use --rerun, --start +NAME, or --goal +NAME argument to rerun skipped tasks.

発生した問題

データソースにより、現状の設定では複数のエラーや想定外の結果となったケースが発生したので、問題別の対策を行いました。
参考リンク:Embulk 0.8 documentation

OutOfMemoryError

エラーログ。

2016-12-01 10:04:47 +0000 [ERROR] (task-thread-0): Uncaught exception. Task heartbeat for at-least-once task execution is not implemented yet.
java.lang.OutOfMemoryError: Java heap space

発生しても一応処理は進みましたが、問題なのでヒープサイズの最大値を設定しました。
1024の倍数で設定しますが、オペレーター(sh>:などの事)がembulkだとオプションが実行できない様なので、sh>:に変更しました。

timezone: UTC
 
+guess:
  sh>: embulk guess embulk/guess-redshift-output.yml -o embulk/config-redshift-output.yml

+load:
  sh>: embulk -J-Xmx2048m run embulk/config-redshift-output.yml

ロード件数の不一致 & 既存のテーブルにロード失敗

件数は下記で確認しました。

データソースの行数確認
$ wc -l データソースのパス
ロードされた件数確認
SELECT count(*) FROM テーブル名;

対策

データソースにカラム名のヘッダーを追記しました。方法としては、ヘッダーのみのファイルを作成し、データソースと結合します。ファイルサイズが大きいと、エディターで記述しようと開いたり保存するだけでも時間がかかるのでコマンドを使うのが効率的かと思いました。
注意点として、ヘッダーファイルは最後に改行しておきます。そうしないとヘッダーを記述した1行目のお尻にデータソースが結合されてしまいます。 また、1行目はヘッダーとして扱うので、プレフィックスで複数のデータソースを読み込む場合は全てにヘッダーを結合しておきます。

$ cat ヘッダーファイル データソース名 > 結合したファイル名

YAMLの作成ミス

データソースによってはカラムの型の設定が誤認識されることが有りました。
誤認識の内容は、圧縮形式、ヘッダー有無、カラムの型設定でした。

対応

カラムの方はとりあえずstringにして事なきを得ました。
一応、実行ログを確認して、「skipped line」と出て来る場合は、表示された行が型に適応していないので、適切な型を設定しなおします。

in:
  type: s3
  bucket: S3のバケット名
  path_prefix: S3内の対象ファイル名(プレフィックスで読込み可能)
  endpoint: s3-ap-northeast-1.amazonaws.com
  access_key_id: XXXXX
  secret_access_key: XXXXX
  decoders:
  - {type: gzip}
  parser:
    charset: UTF-8
    newline: CRLF
    type: csv
    delimiter: "\t"
    quote: '"'
    escape: '"'
    trim_if_not_quoted: false
    skip_header_lines: 1
    null_string: ""
    allow_extra_columns: false
    allow_optional_columns: false
    columns:
    - {name: ID, type: string}
    - {name: AMOUNT, type: string}
  ...

また、Digdagの実行ファイルもguessから実行しない様に修正する必要があります。

timezone: UTC
 
+load:
  sh>: embulk -J-Xmx2048m run embulk/config-redshift-output.yml

Digdag再実行時の注意点

前回の実行で成功したタスクはスキップされるので、全てのタスクを再実行する場合は --rerun もしくは -a を追記して実行します。
参考リンク:Digdag | Command reference

$ digdag run 実行ファイル名 --rerun

さいごに

今後も問題が発生すれば記事にしていこうと思います。