Dev Study
AWSサービスの内部原理 コース

51. Kinesisは追記ログ — 読んでも消えないから複数の読者が独立に進める

Kinesisが「読んでも消えないログ」であること、そして複数の読者が互いに邪魔せず同じデータを進めるしくみを、上から下へ図で追っていきます。

① ストリーム = シャードの集合、シャード = 追記されるレコードの列

ストリームKinesis data stream = シャードの集合
putのたびに末尾へ追記
シャードAレコードの列
シャードBレコードの列
シャードCレコードの列
各レコードの中身
#100
#101
#102
#103 …末尾に伸びる一方向の列
1レコードsequence number + partition key + data blob(最大1MB)
  • 「A Kinesis data stream is a set of shards. Each shard has a sequence of data records. Each data record has a sequence number that is assigned by Kinesis Data Streams.」(key-concepts)
  • data blobは最大1MB。Kinesisは中身を解釈も変更もしない(immutable sequence of bytes)。
  • sequence numberは書き込み(putRecord / putRecords)の後にKinesisが採番し、「同一シャード内でpartition keyごとに一意」。同じpartition keyのsequence numberは概して時間とともに大きくなる。
  • partition key(Unicode文字列、最大256文字)はMD5ハッシュで128ビット整数に写像され、各シャードのハッシュキーレンジによってレコードの行き先シャードが決まる。(key-concepts)

ストリームの実体は「末尾にレコードを追記し続ける列(シャード)」の集まり。DynamoDB編のStreams(変更ログ)で見た「追記ログ」構造そのもので、Kinesisはそれを汎用イベントのために提供したもの。書き込みは常に末尾へ、途中の書き換えや削除は起きない。

② 読んでもレコードは消えない — 消えるのは「保持期間の満了」だけ

レコードをput
失効の条件は満了だけ(読んだかどうかは無関係)
保持期間中何度でも・誰からでも読める
コンシューマが「読んだ」ことでは消えない
保持期間の満了はじめてアクセス不能になる
  • 「The retention period is the length of time that data records are accessible after they are added to the stream. A stream's retention period is set to a default of 24 hours after creation.」(key-concepts)— いつまで読めるかを決めるのは「追加からの経過時間」であって、誰かが読んだかどうかではない。
  • 保持期間の可変レンジ:最小24時間〜最大8760時間(365日)。IncreaseStreamRetentionPeriodで延長、DecreaseStreamRetentionPeriodで短縮。24時間を超える保持は追加課金。(key-concepts)
  • 耐久性の面でも公式は「The elasticity of Kinesis Data Streams enables you to scale the stream up or down, so that you never lose data records before they expire.」と述べる(introduction)— 期限(expire)前にレコードが失われることはない、という保証。

ここがSQSとの本質的な分かれ目。レコードは「消費されたから消える」のではなく「保持期間が来たから消える」。読み取りは非破壊で、同じレコードが期限まで残り続ける。この一点が、次の「複数の読者が独立に進める」を可能にする土台になる。

③ 位置(カーソル)は読者ごと — だから複数アプリが同時・独立に進める

共有ログ#100〜#104…(シャード内のレコード列)
期限まで全員に見える
各アプリは「自分の読み取り位置」を進めるだけ
カーソルA集計アプリ:いま#102を処理中
カーソルBアーカイブアプリ:いま#100を処理中
互いに影響しない排他もロックもない
  • 「There can be multiple applications for one stream, and each application can consume data from the stream independently and concurrently.」(key-concepts)
  • Kinesis Client Library(KCL)は、データ消費に関するメタデータ(どこまで読んだか等)をDynamoDBテーブルに保存する(現行KCLはアプリごとに3テーブルを作成)。アプリ名はAWSアカウント+リージョン内で一意で、DynamoDBの管理テーブル名として使われる。つまり「読み取り位置」はストリーム側ではなくアプリ側に紐づき、読者ごとにカーソルが独立する。(key-concepts / Kinesis Client Library, Application Name)

ログは1本を共有するが、「どこまで読んだか」は読者ごとに別々に持つ。だから集計アプリが先に進んでいても、アーカイブアプリは自分のペースで後ろから読める。Lambda編で見たストリーム系のイベントソースマッピングが「シャードごとにカーソルを進めるpull型」だったのと同じ発想で、カーソルの持ち主が消費側にいるのがポイント。

④ 公式の型:1本のストリームを「集計」と「S3アーカイブ」が同時に読む

producers例:Webサーバのログ、クリックストリーム
同じレコードを2アプリが独立に読む
1本のストリーム非破壊の共有ログ
それぞれの出力先へ
アプリ1:集計running aggregatesを計算
アプリ2:アーカイブデータを圧縮してアーカイブ
DynamoDB最新の集計 → ダッシュボードが読む
Amazon S3圧縮データの長期保管
  • 「two applications can read data from the same stream. The first application calculates running aggregates and updates an Amazon DynamoDB table, and the second application compresses and archives data to a data store like Amazon S3. The DynamoDB table with running aggregates is then read by a dashboard for up-to-the-minute reports.」(introduction)
  • 「multiple actions, like archiving and processing, can take place concurrently and independently.」(introduction)

これはこちらの創作ではなく公式ドキュメントが挙げる代表例。1本のログを、性質のまったく違う2つの用途(リアルタイム集計 / 低コストな長期保管)が奪い合わず同時に使える。②の非破壊性と③の読者ごとカーソルが揃ってはじめて成り立つ構図。

⑤ SQSとの本質差 — 「破壊的読み取りのキュー」対「非破壊の共有ログ」

SQS破壊的読み取りのキュー:1メッセージ=1処理者
Kinesis非破壊の共有ログ:1レコード=何人でも読者
処理が終わったら
可視性タイムアウト受信すると他者から隠れる
カーソルが進むだけレコードは隠れも消えもしない
「位置」の持ち方
deleteで消す消費=消滅
そのまま残る保持期間満了まで
位置の概念なし消えるので位置が要らない
位置は読者ごとカーソルを各自が持つ
  • Kinesis側の根拠:読み取りは非破壊、レコードは保持期間まで残る、位置は読者ごと(前掲key-concepts / introductionの各記述)。
  • 対比の軸は「排他して1回だけ処理させる(キュー)」か「同じ事実を全員が独立に読む(ログ)」か。SQSの可視性タイムアウト・at-least-once・冪等性は既習(SQS/Lambda編)。この編ではKinesis側の「ログ」の性質を確定させるのが目的。

選択の判断軸はここに集約される。「1つの仕事を誰か1人にやらせて片付けたい」ならキュー(SQS)、「起きた事実を複数の用途が独立に読みたい/後で読み直したい」ならログ(Kinesis)。同じ「メッセージを運ぶ」でも、消えるか残るかで設計が根本から変わる。

⑥ リプレイはログ構造の当然の帰結 — 過去に戻ってやり直せる

#100〜#105 …保持期間内は全部残っている
戻した位置から再処理
通常:前へ進める#103 → #104 → #105
リプレイ:戻すだけ#101から読み直し
新ロジックで再計算#101以降を新しい集計で
取りこぼしを再処理バグ修正後にやり直し
  • カーソルは消費側(KCLがDynamoDBに保存する消費メタデータ)が持つ「ただの位置」なので、保持期間内なら過去のsequence numberへ戻して読み直せる。レコードは読んでも消えないため、同じデータを何度でも再処理できる(②③の帰結)。
  • 戻れる範囲は保持期間そのもの:デフォルト24時間、延長すれば最大8760時間(365日)ぶん過去まで。(key-concepts)

リプレイはKinesisの「追加機能」ではなく、非破壊ログ+読者ごとカーソルという構造から自動的に出てくる性質。だから「新しい集計を過去データに当てたい」「バグ修正後に取りこぼしを再処理したい」が、保持期間の範囲でそのまま実現できる。キュー(消費=消滅)には原理的に無い芸当。

公式ドキュメントで詳しく ↗