【レポート】AWS Summit Tokyo 2017:Sansan がメッセージング (Amazon SQS) でスケーラビリティを手に入れた話: using C# on Windows #AWSSummit

2017.06.01

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

aws-summit-tokyo-2017-longlogo 2017年05月30日(火)〜2017年06月02日(金)の計4日間に渡り、グランドプリンスホテル新高輪 品川プリンスホテル アネックスタワーで行われている『AWS Summit Tokyo 2017』。

当エントリでは2017年05月31日に行われた『Sansan がメッセージング (Amazon SQS) でスケーラビリティを手に入れた話: using C# on Windows』に関する内容をレポートしたいと思います。

(2017/06/20追記:)イベント公式の関連資料及び動画が公開されましたので展開します。

セッション概要

当セッションの登壇者及び概要は以下の通りです。

スピーカー:
神原 淳史
Sansan株式会社
Sansan事業部 開発部 部長

セッション概要:
Sansan では、ビジネスの成長に伴うサービス規模の拡大により、可用性やパフォーマンスに関する課題を抱えていました。本セッションでは、メッセージング (Amazon SQSを採用) の導入によってどのようにしてそれらの課題を解決したか、実例をベースにご紹介します。メッセージング自体は新しい技術ではありませんが、スケーラビリティの課題解決のために非常に有効な手段の 1 つです。全てのソフトウェアアーキテクト、開発者にお送りします。

セッションレポート

Sansanのサービスについて

  • 名刺のデータ化サービスはSansan社内の別組織が開発、運営している
  • Sansanからデータ化サービス側にjpegを投げるとtxtが返ってくる
  • 法人向けのサービスでは名刺データを一元化して組織内で共有できる。いわゆる外交記録
  • 法人向けのサービスはマルチテナント型のクラウドサービス。1つのテーブルをテナントID毎に分割
  • サービス規模の拡大にともなってスケーラビリティの課題が次々に発生した

メッセージングとは

  • メッセージキューを介し、プロセス間やアプリケーション間でデータや制御を伝達する
  • 特徴
    • メッセージは単なるテキスト
    • 処理失敗したメッセージはリトライされる(厳密には再度処理対象となる)
    • 一定回数失敗し続けたメッセージは別キューに退避される(Dead Letter Queue)
  • SansanではAmazon SQS(Standard Queue)を使っている
  • Amazon SQS(Standard Queue)
    • Transaction:No
    • At-most-once:No
    • FIFO:Best Effort

メッセージングによる課題解決の実例

巨大なトランザクション

  • 法人向けサービス:所有名刺の参照、変更可否をユーザー単位で設定可能
  • 権限設定レコードの洗い替え処理を1トランザクションで処理すると、指数関数的にトランザクションが巨大化
解決策
  • ユーザー毎にトランザクションを分割して並列処理化
  • トータルで処理するレコード数は変わらないが、スループットが向上
  • Web Server(EC2) -> SQS -> Consumer(EC2):メッセージ分割 -> SQS -> Consumer(EC2):並列処理 -> DB

終わらないバッチ処理

  • 名刺のデータ化 → 400万件/月の納品
  • バッチ処理、従来はforeachで一件ずつ処理するようは形だったため、データ化の量に比例して処理時間が増大
解決策
  • バッチ処理を1日中並列処理する形に変更
  • 1件ずつ、すぐに後続処理を起動
  • Not Domain Event:Aは次の処理がBであることを知っている
  • Domain Event:Aは後続処理を知らない。Bは事前にEvent AggregatorをSubscribeしておく
  • Publisher(EC2) -> SNS(Event Aggregator) -> SQS(複数のSubscriber Queue) -> Subscriber

急激に変化するデータベース負荷

  • データ化のスループット
  • 時間帯によって負荷が大きく異なる
解決策
  • Consumerで並列度を制御して処理を絞る。負荷を均す
  • Web API(EC2) -> SQS -> Cunsumer(EC2):並列処理 -> DB
  • CunsumerはAuto scaling
  • スレッド並列度はC#のセマフォで(SemaphoreSlimクラス)

低いメンテナンス自由度

  • Sansanのメンテナンス時はデータ化サービス側も停止が必要だった
解決策
  • メンテナンス中はSansan側のConsumerを停止
  • データ化サービスからのデータはSQSにためておく

リカバリ不可能な処理

  • タイムアウト、外部サービス障害時等による処理失敗時
  • メッセージングなしの場合:リトライは自前、リカバリ不可能な場合も
解決策
  • Amazon SQSによりリトライ可能に
  • Dead Letter Queueの活用

メッセージング処理の注意点

冪等性を保証する必要がある

  • Amazon SQSは基本、At-Least-Once Delivery
  • メッセージの処理に失敗した場合リトライされる
  • メッセージが2回以上処理される可能性がある
  • Amazon SQSのFIFO Queue:スループットに制限がある(最大300TPS)、現時点で東京リージョンで使えない。
  • 冪等性はACOID特性を持つRDBで保証する? RDBがボトルネックに。。

順序は保証されない

  • Amazon SQSは順序保証なし。自前で実装する必要がある
  • 結果整合性モデルになることが多い
  • 例えば並列処理でトランザクションを分割している(A〜D)場合
    • AとBしか終わっていない時点ではビジネストランザクションとしては整合性が取れていない
    • A〜Dまで終わるまでデータをユーザーに見せないなど、アプリケーション側で何らか対応が必要となる

まとめ

  • メッセージングにより向上するもの
    • スケーラビリティ
    • 堅牢性
    • 運用性
  • 反面、設計難易度、複雑度は上がる
  • 適性を知り、適切な場面・方法で使用すべし

感想

DB負荷やバッチ処理時間の増加が悩み事となっているシステムは少なからず存在するかと思います。その意味で、Sansanでのメッセージング(Amazon SQS)による課題解決の実例は参考になった方が多かったのではないでしょうか。

メッセージング処理導入の注意点やトレードオフにについても触れられており、締めくくりの「適性を知り、適切な場面・方法で使用すべし」という言葉に強い説得力を感じました。