はじめに
チーム内で R2DBC についての勉強会を開催することになったので、
自分の理解を整理するためにも、R2DBC の概要をまとめておきます。
本記事では、「そもそも R2DBC とは何か?」という点や特徴をまとめていきます。
具体的な実装についてはここでは触れません。
選定条件と背景
今回R2DBCを採用したプロジェクトでは SpringBoot(Kotlin) + gRPC + MySQL を利用した構成です。
要件として大量のリクエストを捌く必要があり、アプリケーション全体を通して可能な限りスレッドをブロックしないノンブロッキング構成を目指しています。
当初は JDBC の利用も検討していましたが、
JDBC では クエリ実行中にスレッドが占有される(ブロックされる) という特性があります。
このブロッキング処理は、高負荷時のスループット低下を招く恐れがあります。
そのため、MySQL を利用しつつもノンブロッキングなデータアクセスを実現できる方法を比較し、R2DBC を検討する流れになりました。
ライブラリ選定
R2DBC を採用する前にいくつか候補を絞ってライブラリを比較しました。
| # | ライブラリ | アクセス方式 | ノンブロッキング | 特徴 | 選定観点での評価 |
|---|---|---|---|---|---|
| 1 | Spring Data JDBC | JDBC | ❌ ブロッキング | シンプル・軽量 | ブロッキングであるため、要件と不一致 |
| 2 | Exposed | JDBC(内部) | ❌ ブロッキング | Kotlinとの相性が良いDSL。当初最有力候補だったが、内部的にJDBCを利用しており、ブロッキング処理となるため非採用 | 同上 |
| 3 | Spring Data R2DBC | R2DBC | ✅ 非ブロッキング | Non-Blocking、且つ、Springとの統合が容易 | 要件を満たすため採用 |
最終的には、
完全ノンブロッキングで Spring との親和性が高い Spring Data R2DBC を採用することになりました。
R2DBCとは?
ここからが本題となりますが、R2DBCの概要について説明していきます。
R2DBC(Reactive Relational Database Connectivity)は、
RDB に Non-Blocking でアクセスするための 仕様(SPI)と、それに準拠したドライバ群 の総称です。
従来の JDBC はBlocking I/O のため、1 リクエストごとにスレッドを占有してしまうという制約がありました。
R2DBC はこの問題を解消し、Non-BlockingなI/Oを実現しています。
R2DBC の特徴
Reactive Streams準拠
Based on the Reactive Streams specification. R2DBC is founded on the Reactive Streams specification, which provides a fully-reactive non-blocking API.
訳: データの流れにBackpressure(処理速度に応じてデータ流量を制限する)を導入したリアクティブプログラミングの仕様を基盤としています。
Kotlin Flow や Java Stream と組み合わせたリアクティブな処理が自然に書ける
リレーショナルデータベース対応
Works with relational databases. In contrast to the blocking nature of JDBC, R2DBC allows you to work with SQL databases using a reactive API.
訳: JDBCのようなブロッキングI/Oとは異なり、SQLデータベースにリアクティブにアクセス可能です。
R2DBC では待ち時間にスレッドを保持しないため、少ないスレッド数でも高い並行処理が可能
スケーラブルな設計
Supports scalable solutions. With Reactive Streams, R2DBC enables you to move from the classic “one thread per connection” model to a more powerful and scalable approach.
訳: 従来の「1接続につき1スレッド」というモデルから脱却し、少数のスレッドで多数の接続を効率的に扱えます。
R2DBC は I/O 操作をノンブロッキングで実行するため、大量のリクエストが同時に来てもスレッドが枯渇しにくく、アプリケーション全体のスループット向上が期待できる
オープンスペックで拡張性が高い
Provides an open specification. R2DBC is an open specification and establishes a Service Provider Interface (SPI) for driver vendors to implement and clients to consume.
訳: ドライバベンダーはSPI(Service Provider Interface)に則って実装し、クライアントはこれを利用する形で拡張性が確保されています。
Spring Boot との統合
Spring Data R2DBC を利用することにより、Repository パターンや設定周りをシンプルに利用でき、既存の Spring エコシステムにそのまま馴染ませることができます。
-
@Transactional を用いた宣言的なトランザクション管理を利用できる
- ※ R2DBC のトランザクションは JDBC のものとは実装が異なるため、R2dbcTransactionManager を利用する
- R2DBCリポジトリ を利用することでSQLを極力書かなくても抽象的にデータアクセスを実現できる
おわりに
本記事では R2DBC の概要について解説しました。
理論上のメリットについて多く記載しましたが、実際には、ノンブロッキングだからといって必ずしも性能が向上するわけではなく、チューニングで苦労する場面も多くありました。
機会(と気力)があれば、その辺りの話も書いてみたいと思います。