5 ポイント 投稿者 GN⁺ 2025-01-17 | 1件のコメント | WhatsAppで共有
  • rqliteは軽量なオープンソースの分散リレーショナルデータベースで、Goで書かれており、SQLiteとRaftをベースに開発されている
  • 2014年から開発が始まり、信頼性と品質を最優先しており、10年以上の開発とデプロイを経た後でも、本番環境で報告されたパニック事例は10件未満にとどまる
  • 分散システムのテストでは複数レイヤーでの綿密な配慮が必要であり、シンプルさの中で品質を維持するという哲学に従っている

テストピラミッド: 効果的なアプローチ

  • rqliteのテストは「テストピラミッド」に従っている
    • テストピラミッド: 単体テストを基盤とし、統合テストと最小限のエンドツーエンドテスト(E2E)を含む構造
  • 効率的でデバッグしやすく、目的志向のテストスイートを提供する

単体テスト: 品質の中核

  • 単体テストは独立したコンポーネントをテストし、速度と正確性のバランスを提供する
  • SQLiteと「shared nothing」アーキテクチャを基盤としているため、ほとんどの機能は単体テストでカバー可能
  • rqlite全体のコード(約75,000行)のうち、単体テストは約27,000行で構成されている
  • テストは数分以内に完了し、開発中に頻繁に実行できる

システムレベルテスト: コンセンサスの検証

  • システムレベルテストはRaftコンセンサスモジュールとSQLiteの相互作用を検証する
  • 主なテスト項目:
    • SQLite文のノード間レプリケーション
    • さまざまな一貫性レベルでの読み取り処理
    • クラスター障害からの復旧とリーダー選出の検証
  • 7000行のテストコードで、単一ノードおよび複数ノード構成での相互作用を包括的にカバーしている

エンドツーエンドテスト: 最小限のレイヤー

  • エンドツーエンドテストは、システム起動、クラスタリング、基本動作を確認するスモークテストの役割を果たす
  • Pythonで書かれており、実際のrqliteクラスターを実行して主要機能を検証する
  • 例: AWS S3へのバックアップ検証
  • 5000行のテストコードに抑える限定的なアプローチを採用し、デバッグコストを最小化している

パフォーマンステスト: 限界を試す

  • パフォーマンステストでは次のようなメトリクスを評価する:
    • 最大INSERT速度
    • 同時クエリ処理
    • メモリ、CPU、ディスク使用量の比較
  • 2GBを超えるSQLiteデータベースのテストも含め、メモリ管理とディスク書き込みボトルネックを分析する
  • パフォーマンス問題を発見し、最適化を通じて安定性を確保する

学んだ教訓

  • 最初からテストを始める
    • 単体テストはシステムへの信頼を築く最も効果的な方法
    • 開発中に単体テストの作成を先延ばしにすべきではなく、統合テストやE2Eテストよりも早くバグを見つけられる
  • テストコードをシンプルに保つ
    • テストスイートは、複雑なリファクタリングや**DRY(Don't Repeat Yourself)**原則に固執する場所ではない
    • 理解しやすいコードを書くことが重要であり、追加のボイラープレートコードも許容すべき
  • テストを検証する
    • テスト作成時には、一時的に期待結果を逆に設定してテストを再実行する
    • 適切に書かれたテストはこの場合失敗するはずであり、それによってテストコード自体の誤りを事前に防げる
  • テスト失敗を無視しない
    • 理解しづらい、あるいはまれなテスト失敗であっても、ソフトウェアについて重要な情報を提供する
    • デバッグが難しい失敗事例は、しばしばコードの致命的な欠陥を発見する機会になりうる
  • 決定論を最大化する
    • システムの自動プロセスを手動で実行できるメカニズムを構築する
    • 例: Raftのスナップショット機能は通常は半自動で実行されるが、テスト中に明示的にトリガーできるよう設計されている
  • 慎重な姿勢を取る(Be Deliberate)
    • より上位レベルの統合テストやE2Eテストは、必要性が明確に証明された場合にのみ追加する
    • 過剰なテストは開発速度やデバッグ速度を低下させる可能性がある
  • 適用して反復する
    • パフォーマンステストではfsync呼び出しが主要なボトルネックであることが確認され、Raftログエントリをディスクに書き込む前に圧縮してディスク使用を最適化した
  • 効率性を重視する
    • 数分で実行可能なテストスイートを維持することで、高速な反復開発が可能になる
    • これはオープンソースプロジェクトの維持と活性化に不可欠な利点である

品質を最優先に

  • テストピラミッドを順守し、各テストレイヤーが明確な目的を持つように設計している
  • 分散システムの複雑さが増すほど、テストのシンプルさを維持することが鍵となる
  • 信頼でき、運用しやすいデータベースを構築することが目標

1件のコメント

 
GN⁺ 2025-01-17
Hacker Newsのコメント
  • 最初のテストが最も難しいが、追加する価値がある。その後のテストはより簡単になる

    • パラメータ化テストは重複コードを減らし、多様なテストを可能にする
    • 制約条件を徹底的に検証できる場合に有用
    • Propテストは一貫性と不変条件の検証に役立つ
    • 実際にテストできているかを確認するため、ミューテーションテストを使うことが重要
  • プロジェクトへの献身が印象的

  • テストピラミッドの考え方は理解できるが、すべてのレベルが揃っていないことが多く、これを早急に改善しなければならない状況

    • 複数のチームと協力する場合、e2eレイヤーを埋める作業は誰も担当しない仕事になりがち
    • Auth0のような認証メカニズムを使っている場合、テストが難しい
    • e2eテストがないとシステムは簡単に壊れうる
    • 自動化されたe2eテストは、問題を容易に特定し、ロールバックできるようにしてくれる
  • FAQにコピー&ペーストのミスがあるようだ

  • Jepsenレポートを期待している

  • 動画形式でも楽しめた

  • パフォーマンステスト環境がうらやましい

  • rqliteを使ったことがあり、そのシンプルさがよく伝わっている

  • 決定論的シミュレーションテストについて意見を求めている

  • rqliteが実運用環境で使われているのか気になっている

  • rqliteは独創的で天才的なプロジェクトだ