Slide 1

Slide 1 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた CQRS+ESを Kinesis,Spark,RDB,S3でやってみた @ma2k8 Tsubasa Matsukawa スタディサプリ/Quipper Product Meetup #3

Slide 2

Slide 2 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた About me @ma2k8 Tsubasa Matsukawa スタディサプリEnglishのサーバーサイドとインフラを 担当しています。 2

Slide 3

Slide 3 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた Agenda | 01 CQRSとは 02 EventSourcingとは 03 CQRS+ESとは 04 スタディサプリENGLISHにCQRS+ESを導入する前の課題 05 CQRS with Embulkの導入 06 Spark,Kinesis,S3,RDBでCQRS+ES 07 まとめ 3

Slide 4

Slide 4 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた CQRSとは 01 4

Slide 5

Slide 5 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた コマンドクエリ分離原則 ~ Command and Query Responsibility Segregation ~ ➔ ざっくりいうと ◆ Commandは副作用を伴う処理(更新系) ◆ Queryは値だけ返す処理(参照系) ◆ この2つをわけようという考え(CQS)をアーキ テクチャへ適用したもの 5

Slide 6

Slide 6 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた メリット ➔ 参照はページングが必要なケースも多く、更新系のときと同じロジックで組み 立てるのはかなりしんどいので、参照する時の形で保存し、値を取って返だ けにすることでシンプルにできる ➔ これによりアプリケーションのコードがシンプルになり、参照系の計算量もか なり減る ➔ 一定以上の規模、複雑さを持つアプリケーションではかなり有用なアプロー チとなる 6

Slide 7

Slide 7 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた たとえば・・・・? 7

Slide 8

Slide 8 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた ゲームの巨大ロボットの部位破壊を例にしてメリットの一部を紹介 ➔ 攻撃を受けてHPを減少させる処理(更新系)は、どの箇所に受けたダメージ か、その箇所はすでに破壊済みか(壊れていたらHPの減少なし)などのロ ジックを挟むので各部位の現状の状態を計算しないといけない ➔ しかし、全体のHPを表示する(参照系)のに更新系に必要なロジックを挟むの は煩雑で、部位数が多いと重くなってしまうので、更新系が走るタイミングで 全体のHPをどこかに保存しておくことで参照系がシンプルになります 8

Slide 9

Slide 9 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた デメリット ➔ Command/Queryの保存先、同期の方法を考える必要がある 9

Slide 10

Slide 10 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた EventSourcingとは 02 10

Slide 11

Slide 11 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた Event Sourcing ➔ データではなく、イベントを主役とするパターン ➔ 発生するイベントはすべて記録し、基本的に追加しかしない ➔ 対となる概念は「State Sourcing」 11

Slide 12

Slide 12 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた メリット ➔ State Sourcingでは消えてしまう、有用な履歴情報をすべて残せる ➔ 後で「あの情報欲しいな」と思い直したときに、積み上げたEventから好きな 状態に復元することができる ➔ Eventをhookに様々な処理が書ける。マイクロサービス文脈でも有用 12

Slide 13

Slide 13 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた デメリット ➔ Eventの数が多くなると状態を計算する処理のコ ストが大きい ➔ 任意のタイミングでスナップショットデータをつくっ て回避する 13

Slide 14

Slide 14 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた CQRS+ESとは 03 14

Slide 15

Slide 15 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた CQRS+ES ➔ CommandとQueryの結合をEventで行う ➔ QueryをEvent契機で更新していく ➔ Queryはカウンターキャッシュ的に更新されていくイメージ 15

Slide 16

Slide 16 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた 16

Slide 17

Slide 17 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた スタディサプリEnglishに CQRS+ESを導入する前の課題 04 17

Slide 18

Slide 18 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた データの持ち方 ➔ スタディサプリENGLISHではリリース当初から学習ログをEvent Sourcingで RDBに保存する設計になっていた ◆ 立ち上げ期の保存場所としては妥当 ◆ State Sourcingに振っていないのでデータが残っている点もGood ➔ その学習ログを都度集計してクライアントがほしい形に加工していた 18

Slide 19

Slide 19 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた データが増え、つらみが・・ ➔ 学習者のグループを管理する要件が追加され、学習履歴一覧ページが誕生 してしまい、都度集計の重さが実用に耐えなくなってしまった ➔ ただ表示したいだけなのにロジックもめちゃくちゃ複雑 ➔ 集計しないと学習状況がわからないので、学習日数などでソートしてページ ングするのに、全学習者分の集計が必要となり、重・・・・ 19

Slide 20

Slide 20 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた これではスケールしない 20

Slide 21

Slide 21 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた CQRS with Embulkの導入 05 21

Slide 22

Slide 22 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた スケールしないので、 まずは簡単にCQRSを初めてみた 22

Slide 23

Slide 23 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた 23

Slide 24

Slide 24 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた API 軽くなった 24

Slide 25

Slide 25 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた だが・・・・ 25

Slide 26

Slide 26 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた 一時しのぎのCQRS ➔ APIは軽くなったが、Embulkでの集計処理はデータ量に応じて重くなる ➔ 導入後1年ほどして、集計に1時間を超えるようになってしまった ➔ 結果反映が1h以上おくれるので、ユースケースもかなり限られる ➔ Embulkはとても便利で大好きなツールですが、集計用の巨大な生SQLは ちょっとメンテしにくい 26

Slide 27

Slide 27 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた Spark,Kinesis,S3,RDBでCQRS+ES 06 27

Slide 28

Slide 28 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた それぞれの要素を軽く紹介 ※RDBとS3は除く 28

Slide 29

Slide 29 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた Kinesisとは ➔ マネージドなリアルタイムストリーム基盤 ➔ Consumerを自分で書けるKinesis Data Streamsと、Consumerを書かな いでもs3等、特定の箇所に突っ込んでくれるKinesis Data Firehoseがある ➔ at-least-once 29

Slide 30

Slide 30 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた Sparkとは ➔ Scalaで書かれた並列分散処理フレームワーク ➔ Hadoop MapReduceのDisk IOが重い弱点を、データをオンメモリで処理 することにより解決した ➔ 繰り返し処理、リアルタイム処理などにかなり強い ➔ Scalaで直感的に並列分散処理が書くことができて素敵 30

Slide 31

Slide 31 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた SparkはEMR上で動かしています 31

Slide 32

Slide 32 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた EMRとは ➔ Hadoop,Hive,Sparkなどのクラスタをマネージドに立ち上げることができる マネージドクラスタプラットフォーム ➔ 構築、保守がとても面倒な大規模分散処理基盤をお手軽に立ち上げ、実行 することができ、S3,Dynamo,Redshift等のAWSサービスへのインテグレー ションも容易 32

Slide 33

Slide 33 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた これらを使ってCQRS+ESを 効率よくやる 33

Slide 34

Slide 34 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた Command,Query,Eventの保存場所 ➔ Commandはトランザクション整合性で正規化されたデータを保存する ➔ Queryは結果整合性で、非正規化されたクライアント都合のデータを保存す る ➔ Eventは大量のデータをスキーマレスに保存する ➔ Command,QueryはRDB、EventはS3へ保存することにした 34

Slide 35

Slide 35 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた S3はいいぞ ➔ S3は書き込みを`Prefix毎に3500req/sec` 捌ける ➔ AWSはS3をHubにいろんなサービスへ展開しやすい ➔ 可用性99.99% 耐久性イレブンナイン ➔ 安い ➔ `Full managed object storage` 容量キニシナイ 35

Slide 36

Slide 36 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた Kinesisはイベントの伝播 SparkはQueryの集計で使う 36

Slide 37

Slide 37 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた Kinesis 37 ➔ 状態を都度更新するので、計算コストがかからない

Slide 38

Slide 38 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた Spark 38 ➔ 全Eventを利用した状態の復元や、スナップショット作成は Sparkで高速に行う

Slide 39

Slide 39 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた 切り替えも安心安全 39

Slide 40

Slide 40 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた 並行稼動させ、データに問題がないことが確認できたら切り替える 40

Slide 41

Slide 41 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた まとめ 07 41

Slide 42

Slide 42 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた CQRS+ESは便利 42

Slide 43

Slide 43 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた EventはS3においておくと 分析などで再利用しやすい 43

Slide 44

Slide 44 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた EMR,Spark,Kinesisは 大規模と戦う際にとても有用 44

Slide 45

Slide 45 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた 45

Slide 46

Slide 46 text

#sapurimeetup CQRS+ESをKinesis,Spark,RDB,S3でやってみた ご清聴ありがとうございました 46