Kinesis Data Streams のパフォーマンス設計のメモ

Kinesis Data Streams のパフォーマンスの見積もりでミスをして、特定のシャードで GetRecords.IteratorAgeMilliseconds が徐々に拡大してく事態になった。

ストリームからの出力は RawデータバックアップのためのFirehoseと、ストリーム処理を行うKCLのMultiLangDaemonワーカーをECSのコンテナで行っている。 ストリームのスループットの制約は、1シャードあたり下記のようになっていて、これを超えると ProvisionedThroughputExceeded が起きるが、 今回、1分平均のメトリクスではあるが、シャードのIn/Outレコード数、サイズは到底これに到達しないスループットで稼働していた。

  • 書き込み
    • 1000 レコード/sec
    • 1MB/sec
  • 読み出し
    • 2MB/sec

そして、putRecordsの件数のベースが数%上がった時に、特定のシャードで遅延が生じた。 上のKinesisのデータ流量も、ECSのCPUUtilzation、MemoryUsage上も余裕のある値だったため、当初プログラムの問題を疑って ワーカーを再起動した。再起動で一時的に遅延が治まったものの、また遅延が発生し拡大した。 そこでワーカーの単位時間あたりの処理レコード数が頭打ちになっていることに気づいたので、 シャード数を増やすことで事態はおさまった。

これまでレコード数が増加したときは、GetRecordsのカウントも同様に上昇していたが、今回はGetRecordsのカウントが上がらずにガチャガチャしていることが、 ここに起因すると気づけなかったのが痛かった。また、 Firehoseを1つ設定している場合、OutgoingRecordsや、GetRecords のカウントは2倍になるので、 これも気づきを邪魔していたと思う。 デフォルトのメトリクスだけでなく、自前の部分のパフォーマンスもメトリクスにのせて監視する必要性を認識した。

今回、Kinesisのパフォーマンス上はかなりの余裕があるにも関わらず、ワーカーが極端なボトルネックになっているために 余裕をもたせたシャード数にするにあたって、見積もりよりかなり多くのシャード時間のコストが乗ってしまった。