Jepsen: TigerBeetle 0.16.11
(jepsen.io)- TigerBeetle は、複式簿記処理に特化した OLTP データベースで、安全性と高速な処理性能を目標に開発されている
- Viewstamped Replication 合意プロトコルと strong serializability をサポートし、高競合・高スループットのワークロードに最適化された構造を持つ
- フォールトトレランスと障害復旧性を非常に重視した設計とテスト手順を備え、さまざまな障害状況でもデータ損失なく動作することを目指している
- アップグレード、テスト、運用モデル、クラスター障害復旧性などで さまざまなバグや性能問題 が Jepsen テストによって発見され、対処可能性が改善された
- 最新バージョンでは、Ring ベースのレプリケーション性能、クライアントのエラー処理、ロギング・クエリの正確性 などについて複数の改善とバグ修正が提供されている
TigerBeetle の紹介
- TigerBeetle は 複式簿記 (Double-entry bookkeeping) に特化した オンライン・トランザクション処理 (OLTP) データベース
- Viewstamped Replication (VR) 合意プロトコルに基づく strong serializability を保証し、口座と口座間送金 (transfer) データのみを保存する
- 銀行内部スイッチ、仲介業、チケット発券、電力計量など、取引量が多く並行性競合の激しい環境 に適している
- 単一ノード (Core) がすべての書き込み操作を担う構造で、水平スケーリング (Scale-out) ではなく垂直スケーリング (Scale-up) に注力している
- バッチ処理、IO 並列化、固定スキーマなどの ハードウェアフレンドリーな最適化 により、単一ノードのスループット最大化を目指している
障害復旧性とフォールトトレランス
- TigerBeetle は、メモリ、プロセス、クロック、ストレージ、ネットワーク障害 に対して明示的なモデルと復旧手順を提供する
- データ耐久性は、複製のうち 1 つだけが生存していてもデータ損失がないことを保証する
- すべての複製で記録が破損した場合は、安全に停止する形をとる
- システムのハードウェア/ソフトウェア障害、時計ずれ、ディスク破損、ネットワーク遅延・損失・重複など、さまざまな障害を想定している
- Viewstamped Replication と Protocol-Aware Recovery 手法、データブロックのチェックサムおよび複数レプリカ保存を適用
- ランタイム検証 (assertion) を活用し、エラーやバグ発生時の被害を最小化する
アップグレード方式
- バイナリには 現行バージョンと複数の旧バージョンのコード が含まれている
- アップグレードは、単にバイナリを置き換えるだけで可能
- クラスター内の全ノードが自動ローリング方式でバージョン変更され、ユーザー介入を最小化
- 特定バージョンでコミットされた操作が別バージョンで重複コミットされることを防ぎ、状態不一致の防止に有利
時間モデル
- VR ビューと操作番号 を使った論理クロックと、ハイブリッド物理クロック (physical time) を同時に使用
- リーダーがすべてのレプリカの POSIX 時刻を収集し、誤差範囲内でクラスターを相互同期する
- クロック同期が 60 秒以上失敗するとサービスを拒否する
- タイムスタンプは「Unix epoch 以降のナノ秒」単位だが、実際の POSIX 時刻と 27 秒の誤差が生じる
- うるう秒や負の時刻調整時に内部クロックが遅くなる現象がある
データモデル
- 口座 (account) と 振替 (transfer) の 2 種類のデータ型のみをサポート
- 各フィールドは固定サイズで、不変 (immutable) 原則と unsigned int ベースの設計
- 口座は、ユーザー定義 128 ビット id、台帳 (ledger)、フラグ、作成時刻、カスタムフィールドで定義される
- 振替には debit/credit account id、code、amount、カスタムフィールドなどが含まれる
- 振替は即時実行 (単一段階) と 2 段階 (予約・実行交渉) の両方をサポート
- 保留中送金 (pending) の取消/失効が可能
- 特殊な振替で口座の閉鎖/再開も処理できる
運用モデルとトランザクション
- クライアントは、データ状態の更新または照会のための 単一リクエスト (batch) 単位で動作する
- リクエスト内の各イベントは逐次的に、かつ 原子的 (atomic) なトランザクション として処理される
- 再実行、複数リクエストにまたがるトランザクション、対話型クエリなどはサポートしない
- 強い一貫性 (Strong Serializability) と強いセッション一貫性を提供する
- 各操作の成功・失敗、エラーコードの返却、チェーン (Chain、サブトランザクション) 機能による複合処理をサポート
Jepsen テスト設計
- Jepsen ライブラリを通じた プロパティベース (property-based) テストとフォールト注入 (fault injection) を実施
- LXC、EC2 など多様な環境で 3〜6 ノードのクラスターを対象に実験
- データモデルの制約により従来のリスト・セット形式の一貫性検証が難しいため、全操作順序 (total order) を用いて状態/時間の一貫性を検証
- タイムスタンプベースの一貫性チェック、モデル検証、シミュレーションなど 相互補完的な方式 でエラーを検出
モデル検証と操作生成
- 1600 行超規模の単一スレッド状態機械モデル により、TigerBeetle の動作正確性を細かく検証
- さまざまなエラー条件 (重複 id、不連続タイムスタンプ、残高制約など) とリンクされたチェーンに対する 推論およびロールバック処理
- 検証効率のため、operation・id 生成、状態更新、確率ベースのクエリ組み合わせなど 多様な手法 を活用
フォールト注入
- プロセスクラッシュ (SIGKILL)、一時停止 (SIGSTOP)、ネットワークパーティション、クロック変更など 基本的な障害シナリオ を含む
- バージョンアップグレード、ファイル破損シミュレーション、一部レプリカのみの部分破損など 細かなストレージ障害注入
- ジグザグ (helical) ディスク破損など多様なシナリオにより、データ損失可能性の最小化を検証
主なバグ事例と改善内容
リクエストタイムアウト処理の問題点 (#206)
- TigerBeetle の設計上、クライアントリクエストは決してタイムアウトしない。クラスターから応答を受け取るまで無限に再試行する
- 実際には Java などのクライアントが非同期操作時にタイムアウト例外を発生させることがあり、アプリケーション側で外部タイムアウトを設けざるを得ない
- ネットワークエラーや確定的なエラーを曖昧に隠す設計のため、明確な失敗と不確実なエラーの区別が難しい
- Jepsen は、失敗タイプ (確定/不確実) ごとの返却方式と 再試行オプションの追加 を推奨
クライアントエラーによる JVM クラッシュ (#2435)
- タイムアウト回避のためのスレッド/非同期ラッピングが JVM の segfault 問題を引き起こした
- Java クライアントで適切に初期化されていないフィールドが参照されたことが原因で、0.16.12 で修正
セッション期限切れ時のクライアントクラッシュ (#2484)
- 過剰なセッションによる クライアント強制終了現象
- 0.16.13 からはエラー返却方式に改善
単一ノード障害時の待ち時間急増 (#2739)
- リングベースのレプリケーション方式の弱点により、一部ノード障害時に全体の応答時間が極端に増大
- 原因: 基本的にプライマリが次ノードへ 1 段ずつメッセージを送るため、一部ノード障害時に ack 未受信で待機が発生
- 0.16.30 以降、逆方向 レプリケーションや動的リングトポロジーなどを導入し、障害時の応答遅延を大幅改善
Java クライアント Header API バグ (#2495)
- 空の応答バッチに singleton オブジェクトを使ったことで、ヘッダー・タイムスタンプが誤って共有される問題 が発生
- データ正確性には影響しないが、Header API の結果が汚染されるため、0.16.14 で修正
クエリ結果の欠落 (#2544)
- 0.16.13 バージョンで
query_accounts、query_transfersなどの結果が一部欠落するバグが報告され、応答結果が正しい prefix のみに制限されていた
結論
- TigerBeetle は、金融・会計分野で高い安全性とフォールトトレランスを求める環境 に特化している
- Jepsen シリーズのテストにより、さまざまな 復旧性、一貫性、運用モデル、性能 の課題が明らかになった
- 積極的な協業を通じて、障害復旧性、クライアントのエラー処理、レプリケーションおよびアップグレード自動化 などで実質的な改善が実現した
- 最新バージョンでは、より堅牢な障害対応、接続・応答保証、操作一貫性など、高水準の信頼性を提供する
(この内容の一部は、GitHub、TigerBeetle 公式ドキュメント、Jepsen テストレポートなど、さまざまなオープンソースを参考にして作成された)
1件のコメント
Hacker Newsの意見
参考情報として「Fuzzer Blind Spots (Meet Jepsen!)」の記事も案内、https://tigerbeetle.com/blog/2025-06-06-fuzzer-blind-spots-meet-jepsen/
TigerBeetleの信頼性とスケーラビリティに関する話はいつもJepsenレポートで最後に確認してきたという経験の共有。今回のレポートで複数の問題が見つかったこと、それを迅速に修正し、今後同様のバグが繰り返されないよう内部テストスイートも強化したエンジニアリングの姿勢が良く見えるという評価。この姿勢なら、10年後には金融特化データベース分野で「とりあえずPostgresを使え」と同じくらいのデフォルトの地位に到達していてほしいという期待。aphyrの素晴らしい仕事で多くを学んだという賛辞
TigerBeetleがaphyrによって検証され、約束を守っている姿を見て嬉しいという反応。正しいアプローチが正しい結果につながり得るという希望。実運用ではAccountやTransfer以外のデータは外部システムや別のデータベースに残ることが多いが、そのような信頼性の低い外部システムとTigerBeetleの間でconsistencyや復旧が実際にどう実現されるのかという質問
Jepsenのfuzzer blind spotの投稿を読んでいたなら、今回のTigerBeetleレポートはさらに興味深く感じられるだろうという意見。JNI側のsegfaultの例はRustのようなメモリ安全言語を使っていても防げないかもしれないが、TigerBeetleのZig/TigerStyleアプローチはメモリ安全性の面でも良い証明になっているという評価
「Panic! At the Disk 0」セクションのタイトルセンスに小さく拍手したという感想
Jepsen認証を受けた今回の詳細レポートに深く感銘を受けたという声。まだv1.0リリース前にもかかわらず期待が高く、創業者たちがスレッドで積極的にインサイトを共有している点も別途称賛
分散システムのテストでは、実際にシステム内部で発生した順序や時間をシステム自身が報告し、外部モデルと正確に照合することが、正確な検証のための必須要件である点が興味深く、しかも「はっきり当然」に感じられるという所感
Jepsenレポート、関連ブログ、Antithesis連携コードなどを検討したうえで、テスト範囲と効果を学ぶ意図での質問。TigerBeetleではすでにAntithesisでも包括的なテストを行っていると理解していたが、Jepsenが発見したバグをAntithesisではなぜ捕まえられなかったのかが気になる、AntithesisとJepsenのテストの違い、そして内部テストの範囲が最終的にどう違うのかを具体的に質問
TigerBeetleに関心があるとしつつ、クライアント文書を見る限りCやZigクライアントがない点を不思議に思うという声。TigerBeetle自体がZigで書かれているだけに、そのクライアントは存在しないのか、あるいは開発中なのかという質問
TigerBeetleはすでに大手銀行や証券会社で使われているのかという質問