← AWSサービスの内部原理 コース
53. 拡張ファンアウト — 共有2MB/sの奪い合いをHTTP/2プッシュで解消する
DynamoDB編・Lambda編で見てきた「追記ログを何者が読むか」の総仕上げとして、Kinesisのシャードから複数のコンシューマがデータを受け取る2つの経路——pullで帯域を分け合う共有スループットと、pushで専用帯域をもらう拡張ファンアウト——を図で追っていきます。
① シャードは追記ログ — 読み手がpullで引く
プロデューサPutRecord / PutRecords
GetRecords(pull): 自分で引きにいく
シャード=追記ログ順序を保った不変のレコード列
コンシューマ1台読み取り最大2MB/s/シャード
- 読み取りはpullモデル。コンシューマがGetRecordsを呼んでポーリングする(基礎編「ポーリング vs プッシュ」のpull側)。
- シャード1本の読み取り上限は合計2MB/s(公式表記:「Fixed at a total of 2 MB/sec per shard」)。
- 伝搬遅延(message propagation delay)とは、PutRecord/PutRecordsで送ったペイロードがGetRecordsやSubscribeToShardを通じてコンシューマに届くまでの時間。1コンシューマのとき平均約200ms。
シャードは追記ログで、標準コンシューマはそこから自分でGetRecordsを呼んで引いてくるpull型。1台なら2MB/sをまるごと使え、遅延は約200ms。
② 読者が増えると2MB/sを分け合う
シャード=追記ログ読み取り上限: 合計2MB/s(固定)
コンシューマA約0.67MB/s
コンシューマB約0.67MB/s
コンシューマC約0.67MB/s
3台で均等に読んだ場合の目安- 帯域は足し算で増えない。公式:「they all share this throughput. The sum of the throughputs they receive from the shard doesn't exceed 2 MB/sec」。OSで複数プロセスが同じ物理帯域を奪い合うのと同じ構図。
- 公式が保証するのは「合計が2MB/sを超えない」ことだけで、均等に分配されるとは限らない(図の約0.67MB/sはあくまで均等時の目安)。
- 取り分が減る → 未読が溜まる → 伝搬遅延が伸びる。5コンシューマで平均約1000ms(1台の約200msから悪化)。
- 遅延の悪化は「帯域を分け合う」ことの直接の帰結であって、Kinesisが遅くなったわけではない。
共有スループットでは2MB/sは固定枠を全員で奪い合う。読者が増えるほど1者あたりの帯域が痩せ、伝搬遅延は1台の約200msから5台で約1000msへと伸びる。
③ 「引かせる」をやめ登録ごとに専用線を張る
シャード=追記ログ
登録コンシューマX専用 最大2MB/s
登録コンシューマY専用 最大2MB/s
登録コンシューマZ専用 最大2MB/s
他の台数に依存しない- 公式:「Each consumer registered to use enhanced fan-out receives its own read throughput per shard, up to 2 MB/sec, independently of other consumers.」
- 共有(②)は1本の枠を分ける「割り算」、専有(③)は登録ごとに枠が増える。OSでのリソース共有と専有割当の対比と同じ。
- 各パイプは「up to 2 MB/sec of data per shard, independently of any other pipes or of the total number of consumers」。
- KCL 2.0以降を使うと、全シャードへの登録・購読を自動でセットアップしてくれる。API直叩きなら個々のシャードを購読できる。
拡張ファンアウトは「分け合う1枠」を「登録ごとの専用枠」に変える。台数が増えても1者あたり最大2MB/sは目減りしない——これが読者スケールの鍵。
④ GetRecords(pull)からSubscribeToShard(HTTP/2 push)へ
標準(共有)GetRecordsを何度も呼ぶ(polling)
拡張ファンアウトSubscribeToShardで購読=HTTP/2接続を確立
pull: 取りにいく呼ばれたら返す
push: 押し込むHTTP/2接続上のイベントストリームで連続配信
- pull(GetRecords)=基礎編SQS側の考え方。push(SubscribeToShard)=基礎編SNS側の考え方。Kinesisは同じログに対して両方の読み取り経路を選べるのが特徴。
- 基礎編のHTTP/2(1本の持続接続の上でストリーミングできる)がここで効く。公式:「Kinesis Data Streams pushes the records to you over HTTP/2 using SubscribeToShard」。
- 購読は張りっぱなしではなく最大5分で失効する。受信を続けるにはSubscribeToShardを再度呼んで購読を更新する(呼び出しは登録コンシューマ×シャードの組ごとに毎秒1回まで)。KCL 2.0以降はこの更新を自動でやってくれる。
- push化により、伝搬遅延はコンシューマが1台でも5台でも平均約70ms(共有の200ms→1000msと違い、読者が増えても悪化しない)。
拡張ファンアウトはpull(GetRecords)をやめ、SubscribeToShardで張ったHTTP/2接続の上をKinesisが押し込むpush配送に切り替える。ゆえに遅延は1台でも5台でも約70msで安定する。
⑤ 登録上限とコスト — 「何者が読むか」の設計判断
何者が読む?このシャードのログの読者と遅延要件
共有スループットpull・2MB/sを分け合う
読者少・遅延ゆるくてOK。登録不要・追加コスト無し拡張ファンアウトpush・専用最大2MB/s
読者多・低遅延を各自に保証。要登録(上限あり)・従量コスト- 登録上限: On-demand StandardおよびProvisionedストリームで1ストリームあたり最大20コンシューマ。執筆時点の公式では、On-demand Advantageモードかつ対応リージョン(東京含む)に限り最大50まで登録可能。
- コスト: 拡張ファンアウトには「data retrieval cost」と「consumer-shard hour cost」が発生する(共有側にはこの追加コストは無い)。
- 選択は二者択一ではなくコンシューマ単位。低遅延が要るものだけ登録する運用ができる。
拡張ファンアウトは専用帯域とpush配送と引き換えに、登録上限(標準20)と従量コストを背負う。「同じログを何者が読むか」の答えとして、読者ごとにpull共有かpush専用かを選ぶのが設計の勘所。