Merpay Advent Calendar 2019 の10日目は、 メルペイ サンタチームのバックエンドエンジニアの @execjosh がお送りします。
弊社のキャンペーンを支えるサンタの仕組みについて少しご紹介します。
背景
メルペイにおけるキャンペーンとは、簡単にいうとユーザが何かアクションを起こすとポイントが貰えるものです。これまで沢山のキャンペーンをしてきましたが、中でも特に印象に残るのは「ニッポンのゴールデンウィークまるっと半額ポイント還元!キャンペーン」です。
当時は、キャンペーンといえばポイントの還元を数週間待たないともらえないのが一般的でした。しかし私達はよりなめらかな社会を実現するべく、ポイント還元を数週間後ではなく、翌日付与する仕組みづくりに挑みました。
それは、キャンペーンの対象となるユーザの行動を特定し、ポイントを付与まで行う、完全に人の手を必要としない仕組みです。
メルペイではこの仕組みをサンタと呼んでいます。
サンタという名前は、前日に獲得したポイントを夜のうちにまとめて付与し、翌朝起きたら素敵な気分にさせるという、サンタクロースのイメージから付けました。
サンタのアーキテクチャ
ポイントを付与するには、他のマイクロサービスから流れてくる大量のイベントの中から、キャンペーン対象となるイベントだけを抽出しなければなりません。我々はこの逆の発想でデザインしています。対象ではないイベントをいかに早く特定できるかに着目したのです。
サンタのアーキテクチャは、大きく分けて3つのパーツから形成されます。
- 他マイクロサービスから受信したイベントを処理するハンドラ
- キャンペーンの対象であるかを検証するフィルタ
- ポイントを付与するハンドラ
受信したイベントは、先ずはハンドラに渡ります。その次にフィルタを通って、キャンペーンに一致した場合のみDBに保存され、その情報を基にポイントが付与されます。
他マイクロサービスから受信したイベントを処理するハンドラ
ハンドラは他のマイクロサービスが用意しているトピック毎に、必要に応じて用意しています。例えば、メルカリ内購入やコード決済、本人情報確認などのイベントはハンドラが別々です。
イベントを受信すると、対象になり得るイベントか否かを先ず確認します。関係するイベントは内部用 Pub/Sub トピックに投げ直しますが、それ以外はその時点で処理は終了です。
キャンペーンの対象であるかを検証するフィルタ
フィルタを組み合わせてキャンペーンを定義します。殆どのフィルタがひとつの条件を表現するものです。例えば、1000円以上でないと対象にならない条件は、決済金額のフィルタを使います。
フィルタは、他のマイクロサービスへの負荷を軽減するべく2種類に分けています。
- 決済金額や店舗識別子など、手元にある情報だけで判断可能な1次フィルタ
- 本人確認状態や年齢など、他のマイクロサービスへ問い合わせる必要がある2次フィルタ
1次、2次と順に実行します。一つでも合わないフィルタがあった場合、その時点でキャンペーンに一致しないものとし、処理は終了です。
フィルタを経ると、リワードと呼ばれるレコードがDBに保存されます。
リワードはどのお客さまに、どれくらいのポイントをどのタイミングで付与すべきかを管理しています。
キャンペーンによっては即時型のものと、後日まとめて付与する遅延型のものがあります。一致したキャンペーンが即時型の場合は、先ほどできたリワードの情報を内部用 Pub/Sub トピックにパブリッシュします。
一方で遅延型の場合は、付与する日時をDBのレコードに添えて保存します。
ポイントを付与するハンドラ
サンタの醍醐味と言っても過言ではない、ポイントの翌日付与は、日次で回るバッチが前日分のリワードをまとめて内部用 Pub/Sub トピックにパブリッシュすることで実現しています。
このパーツは非常にシンプルで、責務範囲は流れてきたリワードの合算とポイント付与を行うことだけです。
最後に
最初はGWのキャンペーンのためにデザインされたアーキテクチャですが、パーツがそれぞれ疎結合に動きますし、フィルタが非常に柔軟で作りやすいため、現在も殆どのキャンペーンに使われています。
一方で、若干の技術的負債もあります。キャンペーンで定められた上限をフィルタで担保することが理想ですが、現段階ではポイント付与のハンドラで担保されているので、今後直していきたいと思っています。
メルペイを使っていただいているお客さまが、何かのキャンペーンでポイント還元を受けたときはこのサンタのことを思い出して心が温まるような気持ちになってもらえると嬉しいです。
追記
Cloud Pub/Sub ではメッセージが1回以上配信されることが保証されています。つまり、2回も3回も同じメッセージが配信される可能性があるということです。そのため、冪等性を担保するようなサブスクライバを用意する必要があります。ちなみに マイクロサービスの冪等性についてのTech Talk もあるようなので、もし冪等性についてご興味がある場合は是非ご参加くださいませ。
明日の Merpay Advent Calendar 2019 執筆担当は、Backend Engineer の @syumai さんです。引き続きお楽しみください。