更新_2024-11-13
- 初期レポートでは、auto-commit が有効なコンシューマーが直近の poll で返されたオフセットを自動的にコミットし、データ損失が発生しうると主張していた。
- しかし複数の読者から、auto-commit コンシューマーは実際には直近の poll ではなく、その前の poll のオフセットをコミットすると反論があった。
- Java Kafka クライアントでの実験結果もこれを裏づけており、クライアントごとに動作が異なる可能性がある。
- auto-commit に関する具体的な主張はレポートから削除されており、さらなる調査が必要である。
背景
- Kafka は、レプリケーション、シャーディング、append-only ログを提供する人気のストリーミングシステムである。
- Bufstream は、クラウド環境でデータガバナンスとコスト効率を優先する Kafka の代替ソリューションである。
- Kafka と同様に、Bufstream は トピック と呼ばれる部分的に整列されたログ群を提供し、各トピックは パーティション に分割される。
- Bufstream は標準 Kafka クライアントと互換性があり、Kafka API を提供するステートレスなサービスである エージェント、データを保存する オブジェクトストア、そして 調整サービス で構成される。
- Bufstream はデータ保存をオブジェクトストレージサービスへ直接書き込むことでコストを削減し、ステートレスで自動スケール可能な VM として運用できる。
クライアント安全性
- Bufstream はさまざまなストリーミングアプリケーション向けに設計されており、安全な動作のために各種クライアント設定オプションを採用している。
- Kafka と同様に
acks = all をデフォルトとし、enable.auto.commit = false に設定してデータ損失を防いでいる。
auto.offset.reset = earliest を用いて、コンシューマーがログ全体を観測できるようにしている。
トランザクション
- Bufstream は Kafka のトランザクションシステムをサポートしており、複雑な構成を通じて弱い形の原子性を提供する。
- コンシューマーは
read_uncommitted または read_committed の分離レベルで動作でき、read_committed は一部の現象(G1a、G1c)を防ぐ。
- Kafka、Redpanda、Bufstream のいずれでも G0 現象が発生し、これは文書化された分離レベルと一致していない。
テスト設計
- Bufstream 0.1.0 から 0.1.3 までをテストし、Jepsen テストライブラリと Java Kafka Client を使用した。
- テストではさまざまな障害を注入し、Bufstream の安全性を評価した。
キュー
- Kafka のデータモデルに合わせたキューのワークロードを設計し、Bufstream で使用した。
- 各論理プロセスはプロデューサー、コンシューマー、管理クライアントを実行し、さまざまなキーに対してレコードを送信する。
中断
- 予想外の結果に基づき、トランザクションを中断しオフセットを追跡するワークロードを設計した。
- 中断されたトランザクション後のオフセットを 4 つのカテゴリに分類した: 進行、巻き戻し、さらに巻き戻し、その他。
Bufstream の結果
停止したコンシューマー (#1)
- 0.1.0 から 0.1.3-rc.8 まで、
consumer.poll() 呼び出しが即座に返る一方でレコードを返さない問題が発生した。
- Bufstream は 0.1.3-rc.6 でキャッシュをリフレッシュすることでこの問題を解決した。
停止したプロデューサーおよびコンシューマー (#2)
- 0.1.3-rc.6 でも
InitProducerId 呼び出しや listOffsets 呼び出しが失敗する問題が発生した。
- Bufstream は追加のポーリングロジックを導入して問題を解決した。
誤った 0 オフセット (#3)
- 0.1.0 から 0.1.3-rc.2 まで、誤った 0 オフセットが割り当てられる問題が発生した。
- Bufstream は 0.1.3-rc.6 でこの問題を解決した。
トランザクション書き込み損失 (#4)
- 0.1.2 では、コミット済みトランザクションのレコードが消失する問題が発生した。
- Bufstream は 0.1.3-rc2 で問題を解決した。
サーバー側フィルタリングによる書き込み損失 (#5)
- 0.1.3-rc.8 では、軽微な障害への反応として書き込み損失が発生した。
- Bufstream は 0.1.3-rc.12 で問題を解決した。
Kafka の結果
誤解を招くエラーメッセージ (KIP-588)
ProducerFencedException がトランザクションタイムアウト時にも発生する問題がある。
- Kafka チームにエラーメッセージの変更を推奨している。
コンシューマー終了時の無限待機の可能性 (KAFKA-17734)
Consumer.close() 呼び出しがネットワーク IO で無限待機する問題がある。
- KAFKA-17734 でこの問題を追跡している。
トランザクション失敗後の予測不能なコンシューマーオフセット (KAFKA-17582)
- トランザクション失敗時におけるコンシューマーオフセットの意図された動作について、文書が不足している。
- コンシューマーは中断されたトランザクション後にオフセットを巻き戻すことも、そのまま進めることもある。
1件のコメント
Hacker News の意見
Kafkaで発生する問題を調査している中で、見えない書き込みが見つかった。これは、遅延した Produce メッセージが将来のトランザクションに含まれ、トランザクション保証に違反する可能性を示している。Kafka Java Client がリクエストのタイムアウト時にシーケンス番号を再利用できるのではないかという疑いもある。Kafka にはさらに多くのテストが必要だ
Bufstream の製品ページを見て、次の2つの記述がどう両立するのか気になった
Kafka の auto-commit 機能について驚いた
Kafka トランザクションプロトコルには根本的な問題があり、修正が必要だ
Kyle が NATS Jetstream をレビューしたことがあるのか気になる
bufstream の GitHub プロジェクトが見つからなかった。手がかりがあるのだろうか
関連するブログ記事とドキュメントを読んだ後、Kafka は "exactly once delivery" を "read-process-write operation" の特性として定義している。これはトランザクションとして説明したほうがよさそうだ
"トランザクションは一部または全部を観測できる" という文言は、"コンシューマーは一部または全部を観測できる" と読むべきだと思う
このソフトウェアは何に使うものなのだろう。計測用? ブラックボックス?