はじめに
皆さんこんにちは。
データ加工ジョブを作成するときに気を付けないといけないのは、冪等性ですよね。
AWS Glueでジョブを作成するときも冪等性は非常に重要です。
Glueのブックマーク機能(更新されたファイルのみを自動で判別してそのファイルだけ処理してくれる機能)を有効化した場合に、エラーが発生しても冪等性が担保されるのか?ということについて確認してみたので、記事にしてみます。
ここでいう "エラーが発生しても冪等性が担保されている" とは、エラーが起きてジョブが失敗してしまっても、ジョブを再実行すれば最終的に正しい出力になることを言います。これが担保されていれば、エラーが起きても何も考えずにとりあえず再実行すればOKなので運用が楽になりますね(ジョブの実装自体にバグがあったりする場合は別です)。
想定する状況
以下のような状況を考えます。
- inputファイルのjsonをS3に格納する
- 4つのjsonファイル
- Glueジョブを実行する
- Glueジョブのブックマーク機能は有効化されている
- 2つのファイルが出力されるが、途中でジョブがエラーとなる
- ジョブが成功していたら、4つファイルが出力されるはずだった
- ジョブを再実行する
- ジョブが成功する
さて、この図の???はどうなっているでしょうか。
考えられる選択肢
以下の3つのパターンを考えてみました。さて、どれになるでしょうか??
パターン①
エラー時に出力された2つのファイルはそのままで、再度最初からジョブが実行されて4つのファイルが新規作成されるパターンです。途中まで実行されたことがなかったことになって、もう一度ジョブをやり直しているイメージですね。
このパターンだった場合は、元々のファイル2つが残ってしまっているので、冪等性が担保されていないことになります。
パターン②
エラー時に出力された2つのファイルはそのままで、残りの2ファイルだけ新規に作成されるパターンです。どこまで実行したかが記憶されていて、その途中から実行されたイメージですね。
このパターンの場合は、最終的な4ファイルが出来ているため、冪等性が担保されていると言えます。
パターン③
エラー時に出力された2つのファイルが上書きされて、残り2つのファイルは新規に作成されるパターンです。①のように最初から実行していますが、中途半端に出力した2ファイルは上書きするイメージです。
このパターンの場合は、②と同じく冪等性が担保されています。
②との違いは、元々の2ファイルがノータッチか上書きされるかどうかの違いです。
正解の挙動
確かに、中途半端に出力した2つのファイルの中身も中途半端に出力されている可能性もあるから、上書きしたほうが確実ですよね。
ということで、Glueのブックマーク機能はエラーが起きても再度実行すればOKで、冪等性が担保されていると言えます。
ちなみに、ジョブが成功した後に、inputデータを何もいじらずもう一度実行すると、ジョブは成功しますがoutputファイルには何の変化もありませんでした。つまり、Glueのブックマーク機能はエラー時だけでなく成功した場合でも冪等性が担保されていました。ブックマーク機能、良き!
注意事項
今回はS3をインプットにしたので、S3のオブジェクトのタイムスタンプが更新されたものを勝手に差分データとして読み込んでくれました。ただ、これがS3ではないJDBCデータソースなどの場合は、タイムスタンプなどは見ずにブックマークキーとなるカラムで対象を判別するので気を付けてください。
また、今回の冪等性の挙動も変わる可能性があります。
(参考)今回のエラー時の挙動をどのように検証したか
最初は、S3のoutputフォルダにファイルが数個できた瞬間にジョブを手動でstopする方法を試しました。
ですが、これだとstopしても結局全てファイルが出力してしまったため、うまくいきませんでした。
そのため、以下の方法で検証しました。
- 出力する際に、あるカラムでパーティションを作成するようにしておく
- そのパーティションのvalueが、例えば1/2/3/4の4種類だとする
- その際、output/key=4 だけをバケットポリシーでGlueのロールから書き込めないようにしておく
- 一応、この下に追加したバケポリの例※を記載しておきます
- こうすれば、key=1~3は書き込めるので途中までファイルが出力されるが、key=4は書き込めないため途中で権限エラーとなる
※ バケポリの例
{
"Sid": "Example",
"Effect": "Deny",
"Principal": {
"AWS": "arn:aws:iam::123456789012:role/Glue_role_XXX"
},
"Action": "s3:",
"Resource": [
"arn:aws:s3:::sample-bucket/output/key=4/*",
"arn:aws:s3:::sample-bucket/output/key=4"
]
}