More Related Content Similar to Sansanがメッセージング (SQS) でスケーラビリティを手に入れた話 (20) Sansanがメッセージング (SQS) でスケーラビリティを手に入れた話2. 自己紹介
• 神原 淳史 @atsukanrock
• Development Manager at
• Interested in
• Domain-Driven Design
• C# / .NET
• Enterprise Integration Patterns
7. マルチテナント型クラウドサービス
tenant_id biz_card_id given_name family_name email …
xxx 11111 太郎 山田 … …
xxx 22222 二郎 鈴木 … …
xxx 33333 三郎 佐藤 … …
xxx 44444 四郎 田中 … …
yyy 55555 五郎 高橋 … …
yyy 66666 六郎 山本 … …
yyy 77777 花子 中村 … …
テナント (≒組織) 内で
データ共有
DBテーブルをテナント毎に分割
8. サービス規模の拡大
2014 2015 2016 2017
Tenants
2014 2015 2016 2017
Users
2014 2015 2016 2017
Biz Cards
2014 2015 2016 2017
Maximum Users Per Tenant
2014 2015 2016 2017
Maximum Biz Cards Per Tenant
スケーラビリティの
課題が次々に発生
12. ミドルウェア
Amazon SQS
Standard Queue
Amazon SQS
FIFO Queue
Azure Storage
Azure
Service Bus
MSMQ
PaaS Yes Yes Yes Yes No
Transaction No No No Local Distributed
At-most-once No Yes No Yes Yes
FIFO Best effort Yes Best effort Yes (w/ session) Yes
現Sansanで採用
16. 巨大なトランザクション
所有名刺の参照・更新可否を
ユーザ単位で設定可能
0
5,000,000
10,000,000
15,000,000
20,000,000
25,000,000
30,000,000
35,000,000
40,000,000
0 1,000 2,000 3,000 4,000 5,000 6,000
権限設定レコード数
ユーザ数
権限設定レコードの洗い替え処理を
1トランザクションで処理すると、
指数関数的にトランザクションが巨大化
20. 終わらないバッチ処理
0
500,000
1,000,000
1,500,000
2,000,000
2,500,000
3,000,000
3,500,000
4,000,000
4,500,000
DIGITIZATIONS/MONTH DIGITIZATION VOLUME TREND
21. Non-scalable Design
var targetBizCards = GetBizCardsByDigitizedTimestamp(from, to);
foreach (var targetBizCard in targetBizCards)
{
DoSomething(targetBizCard);
}
0
500,000
1,000,000
1,500,000
2,000,000
2,500,000
3,000,000
3,500,000
4,000,000
4,500,000
2016-05
2016-06
2016-07
2016-08
2016-09
2016-10
2016-11
2016-12
2017-01
2017-02
2017-03
2017-04
DIGITIZATIONS/MONTH
DIGITIZATION VOLUME TREND
処理時間がデータ化の量に比例
23. Domain Eventとは
NOT Domain Event Domain Event
Operation A
Operation C
Operation A
A Completed Event
Operation B Operation C
B Request C Request
Aは後続処理を
知らない
Operation B
Aは次にBなことを
知っている
Event Aggregator
事前にEvent AggregatorにSubscribe
26. 急激に変化するデータベース負荷
0
10,000
20,000
30,000
40,000
50,000
60,000
70,000
80,000
90,000
100,000
110,000
120,000
WRITES/HOUR
DIGITIZATION THROUGHPUT
27. データベース負荷を安定させる
0
10,000
20,000
30,000
40,000
50,000
60,000
70,000
80,000
90,000
100,000
110,000
120,000
WRITES/HOUR
DIGITIZATION THROUGHPUT
平均値
「後回し」にできれば
負荷が安定
30. while (true)
{
IDisposable throttlingToken = null;
try
{
throttlingToken = await ThrottlingPolicy.EnterAsync();
var message = await MessageChannel.ReceiveAsync();
if (message == null)
{
throttlingToken.Dispose();
var interval = IdleRetryPolicy.GetRetryInterval(++idleCount);
await Task.Delay(interval, cancellationToken);
continue;
}
idleCount = 0;
Task.Run(async () =>
SemaphoreSlimクラス等を
利用してスレッド並列度を制御
Channelからメッセージを取得
ワーカースレッドを起動
※イメージです
42. メッセージングと冪等性
• Amazon SQSは基本、At-Least-Once Delivery
(Standard Queue)
Exactly-Once ProcessingモデルのFIFO Queueもあるが、
遅い & Tokyoに来ていない
• 例外発生等によりメッセージの処理に失敗した場合、
該当処理はリトライされる
冪等性を保証する必要がある
強い一貫性モデル (ACID) を持つRDB等で保証するのが基本
Editor's Notes C#成分はほとんど入っておらず、言語非依存の技術であるメッセージングに関するお話 ユーザが名刺をスキャナーでスキャンすると、Web APIでSansanに名刺画像が送信される
Sansanは受け取った名刺画像をテキストデータにするため、データ化サービスにWeb APIで送信する※データ化サービスは社内の別組織が開発・運用しており、ユーザが触れる部分のSansanサービスとは疎結合
Sansanはデータ化サービスからCallback APIで、名刺テキストデータを受け取る ポイントは、個人の名刺管理ではなく、テナント単位で名刺データベースを構築できる点
右側はDBテーブルのイメージ
他のマルチテナントの設計パターン
データベースごと分ける
データベース内のスキーマを分ける 非公開の数値を含むため縦軸は伏せているが、雰囲気は掴める
Maximum Users Per Tenantの極端な拡大ぶりは特にすごい
Messageは Sansanサービスの特徴的な仕様として、細やかなセキュリティ設定機能がある
名刺というのは個人情報であり、同じテナント内であっても参照制限、更新制限をかけたいという要求が頻繁に出るが、Sansanはそれに対応している
特に企業規模が大きくなればなるほど出やすい要件だが、例えば役員が交換した名刺を一般社員の誰でも参照可能とはしづらい。逆方向は参照可能としたかったりする
左側の図
中央の四角い枠の両側に並んでいるのはユーザで、両方共上からユーザA, B, C, D
中央の四角い枠の中の矢印が、DBの権限設定レコード1レコード分
右側のグラフ
テナント内のユーザ数が増えると、対応するための権限設定レコードは指数関数的に増える
1テナント内の権限設定レコード洗い替え処理が発生することがあったが、整合性を保って処理するために1つのDBトランザクション内で処理していた
結果、そのDBトランザクションが指数関数的に巨大化していた 注意すべきなのは、この設計でスループットが向上するかどうかはDBのパフォーマンス特性に依るので、計測が重要
SansanのDBでは、スループットが向上した
この設計だと、一部は完了、一部は未完了と状態が混在することがあるが、その辺りは後ほど触れる これは、メッセージングを活用した分散並列処理の設計の基本形 いずれもネットワーク越しにアプリケーションを連携するPaaSだが、Amazon SNSはpushベース、Amazon SQSはpullベース
SNSは、モバイルプッシュ通知やSMSメッセージ送信等が可能だが、SQSキューへのメッセージ送信も可能
個人的な想像だが…
データ化サービスでは、精度の維持向上のため、人力入力に頼っている部分がある
現時点ではデータ化のほとんどは日本語の名刺なので、日本語を理解できる人が入力している
自ずと、日本時間の日中にデータ化の量がピークを迎える
急激に変化するデータベース負荷は、データベースに優しくない
データ化処理は、それほど高い即時性は求められない 図にしてしまうと非常に当たり前な感じだが、ポイントは3つ
Digitization Serviceから見ると、Web API Serverは常に即時処理している
実際にはAmazon SQS Queueに溜まっていて、後回しにされることもある
Consumerの並列度制御により、データベース負荷が高くなりすぎない FIFO遅い: 300 transactions / sec ( http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/FIFO-queues.html#FIFO-queues-moving )