
2025/12/09 3:51
Jepsen: NATS 2.12.1
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
(欠落している要素をすべて組み込み、根拠のない推測を除去したもの)
要約
NATS JetStream のデフォルト「lazy‑fsync」ポリシーは、データをディスクにフラッシュする頻度が 2 分ごとにしか設定されていないため、データ損失およびサービス障害の重大なリスクを生じます。ノードがクラッシュしたり、そのブロック(.blk)やスナップショットファイルが破損すると、最大 78 % のメッセージが消失し、クラスターがクォーラムを失う可能性があります(GitHub issue #7549 および #7556)。協調クラッシュでも、全ストリームが削除されるケース (#6888) や永続的に利用不可になるケース (#7556) が報告されています。この問題は、単一ノードのクラッシュでそのノード上のすべてのデータが消去される点と、2 分間隔という設定が安全なフラッシュ前に約 30 秒分のトラフィックを失うリスク(#7564)を伴うため、さらに深刻です。
JetStream v2.10.22 はクラッシュ時に全ストリームを削除するバグ(v2.10.23 で修正済み)が存在し、スナップショットファイルの切断や単一ビットエラーもノードがストリームデータを削除しクォーラム復旧に失敗して永続的に利用不可になる原因となっていました(#7556)。OS のクラッシュとプロセス停止またはネットワーク分離の組み合わせにより、単一ノードの障害でもデータ損失や持続的なスプリットブレインが発生する可能性があります(#7567)。
NATS は lazy‑fsync ポリシーを文書化していますが、現時点でデフォルト設定変更を推奨していません。Jepsen は fsync を「always」に設定するか、ユーザーに対して相関失敗リスクを強調するよう勧告しています。JetStream のドキュメントが主張する線形性(linearizability)と「自己修復・常時可用性」は非同期ネットワークの CAP 定理に矛盾し、Jepsen もこの点を指摘しています。
Jepsen の LazyFS テストは、書き込みをディスクフラッシュ前にバッファリングするシステムで電源障害をシミュレートし、同様の相関ハードウェア障害が類似した失敗を引き起こすことを示しています。NATS は issue #7549、#7556、および #7567 を積極的に調査中であり、クラッシュ削除バグ(#6888)は v2.10.23 で修正済みですが、lazy fsync のドキュメントは残り変更されていません。
本文
NATS JetStream(2.12.1)に関する調査結果
概要
- NATS JetStream は「少なくとも 1 回は配信」(at‑least‑once) を保証しますが、データファイルの破損や電源障害により書き込みを失うケースが確認されました。
- 既知の問題(#6888)は 2.10.23 にて修正済みです。
- その他(#7549, #7556, #7564, #7567)は現在調査中です。
背景
- NATS は Raft を用いてレプリケーションし、線形可能性 (Linearizable) を主張していますが、実際には可用性と完全一致の両立は CAP 定理により不可能です。
- JetStream のデフォルト fsync 周期は 2 分であり、ACK は即時返却されます。これにより、近くの書き込みがディスクへ永続化されず、電源障害等で失われる恐れがあります。
テスト設計
| 項目 | 内容 |
|---|---|
| ライブラリ | Jepsen + JNATS (v2.24.0) |
| 環境 | Debian12 LXC コンテナと NATS Docker イメージ併用 |
| クラスター構成 | 3 ノードまたは 5 ノード、レプリケーション係数 5 |
| フォルト注入 | プロセス一時停止・クラッシュ、ネットワーク分断・パケット損失、ファイル単位のビットフリップや切り捨て(.blk, snapshot) |
| OS レベル電源障害 | LazyFS を利用してシミュレート |
評価指標
- lost‑prefix / lost‑postfix / lost‑middle:ACK されたメッセージが最終読取で見つからないケースをプロセス単位で区分。
- divergence(split‑brain):同一 ACK メッセージがノード間で欠落する事象。
主な結果
| 番号 | 要因 | 影響 | 状態 |
|---|---|---|---|
| #6888 | プロセスクラッシュ | ストリーム削除(全データ消失) | 修正済み (2.10.23) |
| #7549 | .blk ファイル破損 | 1 ノードまたは複数ノードで大量書き込み喪失、分割脳発生 | 未解決 |
| #7556 | スナップショットファイル破損 | ストリーム全削除(クォーラム不可) | 未解決 |
| #7564 | デフォルトの lazy fsync | 2 分間隔での書き込み失われ、電源障害時に数十秒分喪失 | 文書化済み |
| #7567 | 単一 OS クラッシュ + 一時停止 | ACK メッセージの喪失と persistent split‑brain | 未解決 |
詳細
1. .blk ファイル破損 (#7549)
- 5 ノード中 2 ノードで単ビットエラーを注入。
- n1, n3, n5 はそれぞれ 78 % の ACK メッセージを失う(n1: 852,413, n3/n5: 1,167,167)。
- 消失は prefix/middle/postfix 全てに散在し、Swiss‑cheese ライクな欠落が観測。
2. スナップショット破損 (#7556)
- n3, n5 の snapshot にビットフリップを注入。
- n3 がメタデータリーダーになり、jepsen-stream を削除。
- 他ノードはクォーラムが取れず、ストリーム利用不可。
3. lazy fsync 政策 (#7564)
- デフォルト 2 分間隔で flush。
- 単一ノードの同時クラッシュにより、30 秒分の書き込みを失うケース確認。
- 連続する単一ノード故障でもストリーム全消失が発生。
4. 単一 OS クラッシュ + 一時停止 (#7567)
- 1 ノードで電源障害後に再起動し、他ノードはクォーラム形成。
- ACK メッセージが一部のノードで失われ、split‑brain が永続化。
推奨事項
- fsync 周期を “always” に変更(または文書でリスクを明示)。
- スナップショット・.blk ファイルのチェックサム検証を強化し、破損時に安全な削除/復旧機能を実装。
- 文書に「Linearizable でも完全可用性は保証されない」旨を明記。
- 単一ノード障害時のリカバリ手順(リーダー再選、データ整合性チェック)を検証。
今後の課題
- 線形可能性/シリアライズ性 の実際の保証を検証。
- exactly‑once semantics の動作確認。
- クラスター構成変更(ノード追加/削除)の安全手順を確立。
参考文献
- Jepsen 調査レポート(2025年11月)
- LazyFS プロジェクト (INESC TEC)
- NATS JetStream ドキュメント (v2.12.1)
以上が現在の調査結果と推奨事項です。