Cloudflare のグローバルネットワークは 300 か所以上のデータセンター ↗ で構成されています。従来型の集中データベースへ、これらの任意の地点からクエリが届くと、いくつかの課題が出ます。
データベースが中央に置かれていると、往復に時間がかかります。Workers のようなステートレス環境から毎回新しい接続を張る場合は、呼び出しごとに複数回のラウンドトリップが必要になり、さらに遅くなります。
従来のデータベースは、同時接続数に上限があることがほとんどです。分散トラフィックがそれなりの規模になると、接続枠はすぐに尽きやすくなります。
Hyperdrive は、オリジンデータベースへのグローバルな接続数を管理し、キャッシュするクエリ応答を選択的に解析・判定します。これによりデータベース負荷を下げ、クエリを高速化します。
Hyperdrive は、次の方法でデータベースクエリを高速化します。
- Workers の近くで、新しいデータベース接続のセットアップを行う
- データベースの近くで、既存接続をプールする
- クエリ結果をキャッシュする
これにより、Workers からデータベースへ接続するときのパフォーマンスが最適化されます(クエリがキャッシュされるかどうかに関係なく)。
Cloudflare Worker からデータベースドライバーがデータベースへ 直接 接続すると、まず接続セットアップが行われます。安全な接続の検証と確立には、データベースとの複数回のラウンドトリップが必要になることがあります。Worker とデータベースの距離によって、追加のネットワークレイテンシが発生します。
Hyperdrive を使うと、この接続セットアップは Cloudflare Worker と Hyperdrive の間で、エッジ上(Worker のできるだけ近く)で行われます(図のラベル 1. Connection setup を参照)。同じ拠点内で完了するため、レイテンシは大幅に小さくなります。
Workers と Hyperdrive の間の接続の詳細は、接続ライフサイクル を参照してください。
Hyperdrive は、アプリケーションがデータベースへクエリを実行するときに再利用できる接続プールを作成します。
データベース接続のプールは、オリジンデータベースに最も近い 1 つ以上のリージョンに置かれます。これにより、Workers とデータベースの間で新しい接続を張る往復のレイテンシを最小化します。キャッシュされていないクエリでも、発生するネットワークレイテンシをできるだけ小さくします。
プールに既存の接続がある場合、その接続の再利用を試みます(図のラベル 2. Existing warm connection を参照)。 プールに既存の接続がない場合は、データベースへ新しい接続を確立し、その接続でクエリをルーティングします。アプリケーションの運用に必要な範囲で、接続の再利用と新規作成を最小限に抑えることが目的です。
コネクションプーリングの動作と設定の詳細は、コネクションプーリング を参照してください。
Hyperdrive は、データベースへの読み取り(非ミューテーション)クエリのキャッシュに対応しています。
Hyperdrive 経由でクエリが送られると、Hyperdrive はクエリを解析し、書き込み(ミューテーション)か読み取り(非ミューテーション)かを判定します。
読み取りクエリでは、設定した max_age の間、応答をキャッシュします。Worker が後から元のクエリと一致するクエリを送ると、Hyperdrive はオリジンデータベースへ送り返さず、キャッシュした応答を返します。
キャッシュにより、オリジンデータベースの負荷が下がり、クエリの応答時間が短縮されます。
アプリケーションがデータベースへ書き込んでも、Hyperdrive はキャッシュ済みの読み取りクエリ結果を無効化しません。書き込み後に最新データを読む必要がある場合は、クエリキャッシュ を参照し、新鮮なデータが必要な読み取り向けにキャッシュ無効の Hyperdrive 設定を別に用意する方法を確認してください。
クエリキャッシュの動作と設定の詳細は、クエリキャッシュ を参照してください。
Hyperdrive のコネクションプーラーはトランザクションモードで動作します。クエリを実行するクライアントは、トランザクションのあいだ 1 本の接続を通じて通信します。トランザクションが完了すると、その接続はプールに戻されます。
Hyperdrive は、トランザクションまたはクエリのあいだ SET ステートメント ↗ に対応します。たとえば、BEGIN / COMMIT で手動でトランザクションを作った場合、そのトランザクション内の SET ステートメントは有効になります。また、SET コマンドを含むクエリ(SET X; SELECT foo FROM bar;)でも SET コマンドが適用されます。接続がプールに戻されると、接続は RESET されるため、その後のクエリには SET コマンドは効きません。
そのため、1 回の Worker 呼び出しでデータベース操作のために複数の接続を取得することがあり、クエリまたはトランザクションごとに設定を SET し直す必要がある場合があります。SET の状態を保つために複数のデータベース操作を 1 つのトランザクションでまとめることはおすすめしません。そのあいだ接続をほかの Worker isolate が再利用できないため、Hyperdrive の性能とスケールに影響します。
Hyperdrive は、postgres.js および node-postgres ドライバーで実装されている名前付きプリペアドステートメントに対応します。ほかのドライバーの名前付きプリペアドステートメントは、性能が落ちるか、未対応のことがあります。