べき等性パターン(#1)
tl;dr
- べき等大事だよ
- 今回は背景と、べき等ではない例を説明するよ
背景
べき等性(Idempotence)とは
なんらかの理由で、本来は一度だけの処理が複数回実行されてしまう場合があります。処理が複数回実行されても大丈夫な場合、べき等(idempotence)と言います。
なお、名著データ志向アプリケーションデザインでは、「複数回実行することができ、その影響が一度だけ実行したときと同じになるような操作」(P.523)と定義されています。
なぜ、べき等性を気にする必要があるか
処理を正確に一度実行することは一般論として難しいです。Apache AirflowやApache Beam(※)などの分散処理システムでは、
- あるワーカーが処理をする
- 処理が終わったことを報告する前に、ワーカーが死ぬ
- 処理が失敗したと判断され、別のワーカーが処理を実行
などの場合があるので、とりわけ難しいです。
そのため、これらのシステムでは、べき等性を気にして実装することが勧められています。例えば、
Beamでは、
In addition, it’s recommended that you make your function object idempotent. Non-idempotent functions are supported by Beam, but require additional thought to ensure correctness when there are external side effects.
(関数をべき等にした方が良いよ。べき等でない関数もサポートされているけど、正しさを外部システム側で確保する方法を考える必要があるよ)
と、プログラミングガイドに記載されています。
※正確には、それを実行するRunner(Cloud DataflowやApache Spark)
なぜ、この記事を書いているか
「べき等にしたほうが良いよ」としても、実際どう実装すれば良いかは、それほど明白ではありません。
分散システムのOSSなどには、べき等を考慮したコードの例があるので、それを整理し、べき等にしたい時の参考にしようと思った次第です。
パターン0:べき等にしない
どんな時に使う
「べき等にしたほうが良いよ」と書いておいた後ですが、べき等な実装を「常に」する必要はありません。
複数回実行されたとしても困る人が誰もいなければ、我々も気にする必要はないでしょう。
例: AirflowのEmailOperator
Airflowには、EmailOperatorという、メールを送るOperatorがあります。
具体的な処理は、email_backendで指定されるコード(※)で実装されるのですが、SMTPによる処理(send_email_smtp)では、
を行っているだけなので、同じメールが複数回送られる可能性はあります
(処理の途中で失敗しリトライや、タスクの再実行(backfillやclear)
ドキュメントに記載がないのであくまで想像ですが、べき等にしていないのは、
- この処理をべき等にするのが難しい
- EmailOperatorの典型的な使い方は、ETL処理の成功・失敗時の通知なので、二度送られても、メールを読む人がスルーすればすむ話
などの理由ではないでしょうか。
※ 他にSendGridなどの実装が存在
Discussion