本日も乙

ただの自己満足な備忘録。

AWS Lambda Based Amazon Redshift Database Loader を使ってみた(2) 〜失敗したバッチの再実行〜

前回AWS Lambda Based Amazon Redshift Database Loader(Redshift Loader)の使い方を紹介しました。今回はデータロード時に失敗した時の挙動やリカバリ方法について紹介します。

Redshiftへのデータロード失敗の挙動

試しにRedshiftクラスターをリサイズしてRedshift Loaderを実行してみました。

> COPY test_table from 's3://redshift-manifests/manifests/manifest-2016-07-08-01:48:20-3799' with credentials as '' manifest format JSON 'auto'  ACCEPTANYDATE TRUNCATECOLUMNS;

ERROR:  Cannot execute query because system is in resize mode
DETAIL:  System is in resize mode, and ONLY read-only queries are allowed to execute.

リサイズ中、Redshiftへ書き込みができないためCOPYコマンドは失敗します。Redshift Loaderでも次のようなエラーが出てロードに失敗しました。

{
  "error": "{\"test-redshift.xxxxxxxxx.ap-northeast-1.redshift.amazonaws.com\":{\"status\":-1,\"error\":{\"name\":\"error\",\"length\":235,\"severity\":\"ERROR\",\"code\":\"57014\",\"detail\":\"System is in resize mode, and ONLY read-only queries are allowed to execute.\",\"file\":\"/home/rdsdb/padb/src/pg/src/backend/tcop/postgres.c\",\"line\":\"1158\",\"routine\":\"CheckNeedXenCommitDisk\"}}}",
  "status": "error",
  "batchId": "cfd87151-4e7b-41c3-8226-6b06281eb665",
  "s3Prefix": "redshift-loader/buffer/web",
  "key": "buffer/web/20160708-1114_1.json",
  "originalManifest": "redshift-manifests/manifests/manifest-2016-07-08-02:15:20-8697",
  "failedManifest": "redshift-manifests/failure/manifest-2016-07-08-02:15:20-8697"
}

バッチステータスも失敗(error)になっていることがわかります。

$ node queryBatches.js ap-northeast-1 error | jq .
[
  {
    "s3Prefix": "redshift-loader/buffer/web",
    "batchId": "cfd87151-4e7b-41c3-8226-6b06281eb665",
    "lastUpdateDate": "2016-07-08-11:15:21"
  }
]

それでは失敗したバッチを再実行してロードしてみます。

reprocessBatch.js でバッチを再実行します。 node reprocessBatch.js <リージョン> <バッチID> <ロードファイル名> で実行します。

$ node reprocessBatch.js ap-northeast-1 cfd87151-4e7b-41c3-8226-6b06281eb665 redshift-loader/buffer/web
Submitted reprocess request for redshift-loader/buffer/web/20160708-1114_0.json
Submitted reprocess request for redshift-loader/buffer/web/20160708-1114_1.json
Batch cfd87151-4e7b-41c3-8226-6b06281eb665 Submitted for Reprocessing

再実行時の挙動として、以下の処理が非同期で実行されます。

  • バッチで処理するファイルリストが LambdaRedshiftProcessedFiles テーブルから削除される
  • S3にあるファイルを同じ場所にコピーされる。それをトリガーに、Lambda Functionが実行される(新しくバッチが実行される)
  • error となっていたバッチのステータスを reprocessed に変更される

reprocessed ステータスのバッチを検索すると先ほど失敗したバッチIDと同じになっていることがわかります。 バッチのステータスが error から reprocessed に変更しそのバッチを終了させ、新しいバッチを実行することで再データロードを試みます。 なお、そのバッチもデータロードに失敗したら error になります。

$ node queryBatches.js ap-northeast-1 reprocessed | jq .
[
  {
    "s3Prefix": "redshift-loader/buffer/web",
    "batchId": "cfd87151-4e7b-41c3-8226-6b06281eb665",
    "lastUpdateDate": "2016-07-08-11:43:36"
  }
]

このようにコマンド1つで再実行できるのですが、実行するためにはバッチIDとファイルパスを指定しなければなりません。特にバッチIDを1つ1つ調べるのはとても大変です。 なので、次のようなシェルスクリプトを用意します。

このスクリプトaws-lambda-redshift-loader と同じディレクトリに置いて実行することで失敗したバッチすべてを再実行するようにします。

$ cd aws-lambda-redshift-loader
$ wget https://gist.githubusercontent.com/ohsawa0515/ec419ee41e28428fec759260e9555475/raw/d082a98775eafe263785e83b21cdb65d5279c262/reprocess_batch.sh
$ chmod +x reprocess_batch.sh
$ bash ./reprocess_batch.sh

最後に

AWS Lambda Based Amazon Redshift Database Loader において、データロード失敗時に再実行する方法について紹介しました。 Redshiftのメンテナンスウインドウによってデータロードに失敗することがしばしばあるため、このような仕組みを用意しておくことで楽に運用できるようになりました。 次回(があれば)、1回のデータロードに許容できるファイルサイズの上限について調べた結果について紹介します。