CQRSはEvent Sourcingなしで実現できるのか?

CQRSはEvent Sourcingなしで実現できるのか?

933291444e456bfb511a66a2fa9c6929?s=128

かとじゅん

March 24, 2020
Tweet

Transcript

  1. 2.

    © Chatwork あなたは誰? • 加藤潤一(@j5ik2o) • Chatwork社のテックリード • 直近の活動 ◦

    Kafka, S3のEvent Sourcingする ためのプラグインを開発 ◦ Fargateを使った負荷試験ツール の開発
  2. 5.

    © Chatwork CQRS • Command and Query Responsibility Segregation(CQRS責務分離) ◦

    2010年 Greg Young氏 • CQS(Command-Query Separation) をアーキテクチャレベルに適用 • CommandとQueryで要件が違うから わける ◦ 一貫性(強い or 弱い) ◦ データ形式(正規化 or 非正規化) ◦ スケーラビリティ(C:Q=2:8)
  3. 6.

    © Chatwork FYI: C/Qを分離しない場合の弊害 • リポジトリのクエリメソッドが複雑になる ◦ employeeRepository.findByDeptIdsWithEmpNamesWith…(…, …, …)

    • N+1クエリが発生しやすい reservationRepository.findByIds(ids).map { reservation => val a = hotelRepository.findById(reservation.hotelId) val b = customerRepository.findById(reservation.customerId) readModelDto(a, b) } • オブジェクト→DTO変換が非効率 ◦ DTOに変換するときに、UIに合わせて捨てられる項目がある
  4. 7.

    © Chatwork FYI: リードモデルの形式変換をしない場合の問題 • 例えば、入社日がEpocTime(Long値)として保存される場合、そのまま ではクエリのレスポンスに含めることができない。しかしクエリ側から 値オブジェクトに依存ができない。 • これを回避するためにRMUで事前に形式変換する必要がある

    Attribute Type Value EmployeeId String “123456789” JoinedDate Long 1585039714572 ... ... .. JoinedDate#asFormattedString 2020年03月24日 08:48 内部データ表現を意味のある値表現にするにはドメ インオブジェクトを使う必要がある エンコードされたドメインオブジェクト リードしたい値表現
  5. 8.

    © Chatwork C/Qのモデル間の変換・同期の問題はイベントで解決 “The model that is best suited is

    the introduction of events, events are a well known integration pattern and offer the best mechanism for model synchronization.” by Greg Young 最も適したモデルはイベントの導入であり、イベントは よく知られた統合パターンであり、モデルの同期化に最 適なメカニズムを提供します。
  6. 10.

    © Chatwork CQRS+Event Sourcing • 真のデータソースは永続されたイベ ント • そのイベントを使ってリードモデル を構築する

    Event Sourcingは大袈裟で大変と いう意見を聞くので、他の方法がな いか考えてみた
  7. 13.

    © Chatwork アプリケーションからのイベント伝搬方式の問題 • イベントは全順序に並んでいないとうまくリードモデルを構築できない • ステートレスなアプリケーションでは、2層コミット問題とイベント追い 越し問題が起きる (参考文献) スターバックスは2フェーズコミットを使わない

    https://code.google.com/archive/p/gregors-ramblings-ja/wikis/18 _starbucks.wiki 最新状態を保存する DBとキューのトランザク ションを同一化しないと防ぐのが難しい。もしくは DB書き込み成功後にエンキューするプロセスを シャーディングする必要がある
  8. 16.

    © Chatwork まとめ • 単純にイベントを伝搬させるだけでは問題が生じる • ステートレスなウェブアプリケーションでは、 CDC+Outbox方式を採用したほうが無難 • CDC+Outbox方式は、トランザクションログが真の

    データソースでありESの一種であるという理解が必要 • 外形的にはCQRS+SSはできるように見えるが、真の データソースは最新データにはならない。結局はESに 帰結する
  9. 18.