概要
- io_uring を活用した高速な非同期I/Oによるデータベース設計の実験
- Intent/CompletionのデュアルWAL 方式による高スループットと堅牢な耐障害性の両立
- Zig言語 とPoroデータベースでの実装例
- バッチ処理 とハードウェア並列性の最大活用
- 従来の同期I/O前提の設計 を覆す新たなアーキテクチャへの示唆
io_uringによるデータベースI/Oの再発明
- io_uring はLinuxカーネルの非同期I/Oインターフェース
- アプリケーションとカーネル間で リングバッファ を共有
- Submission Queue (SQ) で一括操作登録、 Completion Queue (CQ) で結果取得
- 従来のI/O は逐次システムコール、ハードウェアの並列性を活かしきれない設計
- NVMe SSD などの現代ストレージは数千の同時I/Oを処理可能
- io_uring で複数I/Oをまとめて非同期送信、スループット大幅向上
データベースでの耐久性と一貫性の課題
- 非同期I/O では、書き込み完了前に応答すると耐久性保証が損なわれる
- fsync() による逐次同期は遅いが、耐久性のためには必要だった
- io_uring でも、完了通知を待たずに応答すると障害時にデータ損失リスク
デュアルWAL設計の発想
- Intent WAL :操作意図の記録(非同期)
- Completion WAL :操作完了の記録(非同期)
- プロトコル:
- Intent記録 (非同期)
- メモリ上で操作実施
- Completion記録 (非同期)
- Completionの書き込み完了を確認後 クライアントへ成功応答
- リカバリ時 はIntentとCompletion両方ある操作のみ適用
実装上の工夫
- Zig言語 による実験的実装(Poro、Klay)
- Intent/Completionそれぞれ専用のio_uringインスタンス を用意
- ヘッド・オブ・ラインブロッキング 回避
- サーキュラバッファ によるバッチ書き込み
- バッファ容量の75%到達で一括flush
- CompletionEntry にintent参照・タイムスタンプ・CRC32チェックサムを付与
- リカバリ手順 :
- Intentログ全読込→Completionログ全読込→IntentとCompletionの対応づけ
- CompletionのあるIntentのみ再適用
- チェックサム検証でデータ整合性担保
バッチ処理とパフォーマンス
- 2回の書き込みが必要 なため単一操作のレイテンシは増加
- バッチ処理 では
- Intent記録をまとめて送信
- メモリ操作を並列実施
- Completion記録もまとめて送信
- Completion完了を一括待機
- 2N回の同期書き込み→2回のバッチ送信+完了待ち に変換
- 高負荷時は スループット10倍以上 の改善を確認
- CPUコア数に比例してスケール、I/Oシリアライズのボトルネック解消
得られた知見
- ハードウェア並列性 を最大限活用する設計の重要性
- バッチ化 によるI/Oオーバーヘッドの劇的削減
- 意図と完了の分離 で一貫性と高性能を両立
- 高度なリカバリロジック でランタイムの単純化と信頼性向上
新しいデータベースアーキテクチャへの示唆
- I/Oが安価かつ並列的 になると、従来の前提が崩れる
- バッファプール管理、トランザクションスケジューリング、並行制御 も非同期I/O前提で再考可能
- 同期I/O=耐久性の必須条件 という思い込みの打破
- ソフトウェアアーキテクチャの刷新 でハードウェア性能を最大限引き出す可能性
この実験は、 io_uring と デュアルWAL設計 による新しいデータベースアーキテクチャの可能性を示し、今後のストレージシステム設計に大きな影響を与える知見を提供するものです。