Mercari Engineering Blog

We're the software engineers behind Mercari. Check out our blog to see the tech that powers our marketplace.

AMLチームがどのようにメルペイのデータをSplunkに集め活用しているか

株式会社メルペイのAML/CFTチームでバックエンドエンジニアをしている@hatappiです。
この記事はMERPAY TECH OPENNESS MONTHの7日目の記事です。
前日は同じチームのyagi5からメルペイのAML/CFTシステムを支える技術として AML チームがやってることの全体像が書かれていました。
今回の記事ではその中でも Splunk に対してどのようにデータを集めているかにフォーカスをあてた話を書いていきます。まだ前日の記事を読んでない方はぜひ読んでみてください!!

なぜSplunk にデータを集めるのか

AMLチームでは Splunk にデータを集めることで次の3つのことを行います。

  • 疑わしい取引の検出
  • ダッシュボードの提供
  • データ分析のための基盤提供

疑わしい取引の検出

「疑わしい取引の検出」はお客様にメルペイを「あんしん・あんぜん」に使っていただくためにAML チームが責任をもって行っている重要な業務です。
事前に疑わしい取引を検出するためのルールを作成し、Splunk に入ってくるデータを元に疑わしい取引の検出を行います。
疑わしい取引として判定されたものは後続のシステムへと連携され、本当に不正な取引かを人の目をもって多角的な視点からチェックしています。

ダッシュボードの提供

Splunk は溜めたデータを元に見やすいダッシュボードを作成することもできます。
例えば下記に書いたのは Splunk 公式で提供しているチュートリアルのサンプルアクセスログを表示したものです。
5分ごとに集計したアクセス数を棒グラフに出すこともできます。

f:id:hatappi1225:20190527193750p:plain

またグルーピングして集計したものを折れ線グラフで出すこともできます。

f:id:hatappi1225:20190527193806p:plain

このように必要に応じてデータを様々な形で表現することができます。
また Splunkbase と呼ばれる App や Add on を提供するサービスを使うことで地図上にデータをプロットしたりヒートマップや WordCloud などの表現のバリエーションを増やすこともできます。

データ分析のための基盤提供

AML チームは事前に作成した疑わしい取引を検出するルールがあると書きました。
しかしルールは一度作成して、それで終わりではありません。
新しくルールを作成することもありますし、既存のルールのしきい値を変更することもあります。
メルペイの機能拡張に追従した拡張もあれば、時々刻々と変化する不正な動きに対応するため、ルールも柔軟に変化していく必要があります。

そのためにも Splunk にどんなデータが入っているのかを確認し、検出のしきい値を検討する必要があります。
Splunk を使うことで本番に流入しているリアルタイムなデータにクエリを発行して集計することもできるため、ルールを作るために必要な情報の集約や検討を手軽に行うことができます。
もちろん、個人情報などのセンシティブなデータはマスクされた上で送られてくるためAMLチームがそれらの情報に誤って触れてしまうことがないよう工夫されています。

Splunk にデータを集めるために考えること

Splunk にデータを集めると色々できて面白そう!!と感じていただけましたか?
私も Splunk にクエリを発行して情報を取り出すことがあります。どの地域で何件の決済が発生しているかなどのの情報を見ることができるためキャンペーンの時は Splunk のダッシュボードを眺めて増えていく決済数を見るのは楽しいものです。

ここからはどうやってデータを Splunk に集めているかの話を書いていきます。

AMLチームで扱うデータとは

そもそも今までメルペイのデータ、データと書いてきましたがどのようなデータを扱っているのでしょうか?

AMLチーム では大きく分けて2種類の性質のデータを扱っています。

  1. 決済情報などできるだけ早く取り込みたいデータ
  2. 定期的に取得するデータ

決済情報などできるだけ早く取り込みたいデータ

決済情報はお客様がメルペイをご利用いただく度に作られるため、非常に発生頻度が高いです。
この記事を読んでいる今も決済情報は次々と発生しているでしょう。
さらに決済情報は疑わしい取引を検出するルールで必要になるため非常に重要です。
そのため、できるだけ早くSplunkに取り込む必要があります。

定期的に取得するデータ

取得するデータの更新が1日1回など取得期間が決まっているような場合はバッチを作って定期実行することで対応できます。

ここからは1つ目に紹介した「決済情報などできるだけ早く取り込みたいデータ」をSplunkにどうやって取り込んでいるか書いていきます。

データベースからSyncする?

データを取り込む方法を考えた時、例えばデータが格納されているデータベースを参照することで得られそうです。

Splunk には Splunk DB Connect というアプリが提供されており、これを使うことでデータベースに対して SQL を発行して結果を Splunk に取り込むことができます。

Splunk DB Connect を使うことで Splunk とデータベースの間に Sync するようなバッチを作成する手間を省き、手軽にデータベースからデータを Sync することができます。

しかしこれには2つの問題があります。

  • 同期タイミングと負荷のバランス
  • 各サービスと密結合になってしまう

同期タイミングと負荷のバランス

例えば決済情報は高頻度で入ってくるようなデータなので同期のタイミングが1分に1回や30分に1回の場合その分だけ検出が遅れてしまいます。
疑わしい取引を素早く検出することができればそれだけ問題のある取引を未然に防げる可能性も高くなるため早くデータを取り込むことは大事です。
同期のタイミングを早くすることで解決できそうですが、1秒に1回各サービスのデータベースに SQL を発行するのはデータベース負荷の面からもあまり良い手ではなさそうです。

各サービスと密結合になってしまう

AMLチーム が各サービスのデータベースを参照して Sync した場合、参照しているテーブル情報に変更がでる時は AMLチーム に影響がないかを確認する必要があります。
この確認が漏れてしまうと最悪の場合 Sync に失敗してしまい Splunk でデータを取り込むことができなくなり正しく検出をすることができなくなってしまいます。
さらに各サービスはデータベースに改修が入る機能実装や保守の場合は AMLチーム に毎回連携してもらう必要があるため開発スピードが落ちてしまう懸念もあります。
できるだけ早くイベントを Splunk に取り込みつつ、各サービスには AMLチームを気にせず機能追加や改修をしてもらい方法を考える必要があります。

AMLチームにおけるデータ取得方法

上記の課題から AML チームでは Cloud Pub/Sub を使うことになりました。
今回は Publisher が各サービスで Subscriber が AML チームの構成になります。

f:id:hatappi1225:20190527194217p:plain

AML チームで扱うデータはメルカリ内の取引やメルペイによるiD決済やコード決済など様々な種類があります。

データの種類ごとに Pub/Sub のトピックが作成されており AML チームは各トピックのサブスクリプションを作成してサブスクライブしたデータを Splunk へイベントとして送っています。
しかし Publish されるデータのフォーマットが決まっていない状態だと AML チームではどんなデータがくるか分からないので各サービスに何が入っているのか聞いて回る必要があります。
さらに JSON 形式で Publish をした場合 Publisher 側で Key を Typo したり名前が変更になってしまうとサブスクライブした際にうまく扱えないおそれがあります。
そこで Pub/Sub によるメッセージはすべて Protocol Buffers にシリアライズされて Publish されています。

例えば Transaction という構造体に Id, Amount という2つのフィールドがあったとします。

type Transaction struct {
    Id     string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
    Amount uint64 `protobuf:"varint,2,opt,name=amount,proto3" json:"amount,omitempty"`
}

Publisher は必要な値をうめて Protocol Buffers に Marshal した後に Pub/Sub へ Publish します。

tx := &Transaction{
    Id:     "111-111-111-111",
    Amount: 1000,
}
message, err := proto.Marshal(tx)
if err != nil {
    return err
}
_ := topic.Publish(ctx, &pubsub.Message{
    Data: message,
})

Subscriber は受け取った Pub/Sub の message をデシリアライズすることで型がついた状態で処理することができます。

tx := &Transaction{}
err := proto.Unmarshal(message, tx)
if err != nil {
    return err
}
fmt.Printf("Id is %s, Amount is %d", tx.Id, tx.Amount)
// Id is 111-111-111-111, Amount is 1000 

Protocol Buffersで扱うことで Publisher 側は定義された構造体の情報を埋めることさえ守れば後は自由に開発することができます。

SubScriber 側は受け取ったメッセージをデシリアライズして使うことが出来るので、なんの値が入っているかを認識しながら開発することができます。

サブスクライブしたデータを Splunk におくる

ここまでは各サービスでおきたイベントを Pub/Sub 経由で受け取る話をしました。 subscriber が受け取ったメッセージは Splunk に送るためにいくつかの情報を付与して JSON 形式で送ります。
その際 subscriber は直接 Splunk に送るのではなく Amazon Kinesis Data Firehose を通して Splunk に送っています。

Firehose は destination として S3 や Redshift, Elasticsearch Service を指定できますが Splunk も指定することができます。

f:id:hatappi1225:20190527194422p:plain

そのため subscriber は Firehose にレコードを Put して後は Firehose 側でバッファリングして、Splunk からエラーが返ってくる時はリトライなどをする役目を担ってくれます。

おわりに

今回は メルペイで扱っているデータをPub/Sub 経由で受け取り Firehose を通して Splunk へ送っている話を書きました。

AML チームはあまり表舞台に出ることがないですが、メルペイを「あんしん・あんぜん」に利用していただくためには欠かせないチームです。
今後もメルペイが成長していくにあたって扱うデータの 種類, は増えていきます。
増えるデータに対してどれだけデータを早く扱える状態にして検知するかを考えていく必要があるのでエンジニア観点からも面白いチームだと思います。

今回記事に書いた内容以外にも AML チームでは面白い取り組みをしているので少しでも興味をもっていただいた方はこちらから応募していただけると嬉しいです!
とりあえず話を聞いてみたい方はメルペイ Backendチーム 『カジュアル面談 オープンドア』という場があるのでぜひ参加してみてください!!
まだまだ MERPAY TECH OPENNESS MONTH は続きます!
明日はtkuchikiの記事です!!おたのしみに!!