SE の雑記

SQL Server の情報をメインに Microsoft 製品の勉強内容を日々投稿

SQL Database Hyperscale の構成や特徴を学習する

leave a comment

SQL Database の Hyperscale が Build 2019 で GA され、SLA 付きで使用できるようになりました。
今後、このサービスレベルに触れる機会もあるかもしれませんので、現在公開されている情報を見ながら学習してみました。
(de:code 2019 の登壇が終わったのでようやく、セッションに関係のない勉強ができる…。)

公式のドキュメントは次の情報となります。
FAQ に記載されている内容が「なぜそうなるのか?」を考えると、構成の理解を進める上で役に立つかと思います。

より詳しい情報については、次のドキュメントから確認できます。

■SQL Database との構成の違い

Hyperscale は、Azure SQL Database の一つのサービスレベルとなりますが、従来型のシングルデータベース / エラスティックプールモデルとは大きく構成が異なります。

従来型のモノリシックアーキテクチャ

従来までの SQL Database はモノリシックな DBaaS のアーキテクチャとなっていました。

image

データベースに関しての全ての事象を SQL Server を実行するサーバーで管理する必要があります。

このような構成の場合、次のような要求を満たすことが難しいという問題がありました。

  • サービスの柔軟性
  • ワークロードに応じた柔軟な拡張と縮小
  • 大規模データベースのサポート
  • 稼働マシンの柔軟な変更

Hyperscale のアーキテクチャ

これらの課題に対応するため「クラウド向けの新しい OLTP のデータベースシステムのアーキテクチャ」の研究が行われ、「RDBMS の管理システムの機能を分割し、各機能を独立して展開を行う」という構成が採用されました。
このアーキテクチャについては AWS の Aurora が最初に商用として採用したものとなり、SQL Server ベースでこの構成をとったものが「Azure SQL Database Hyperscale」となります。

Hyperscale では「コンピューティングとストレージを分離する」という構成がとられており、ストレージについても「データとログを分割する」という構成が採用されています。

SQL Server が稼働しているサーバー上で、データベースのファイル (データ / ログ) が確認できますが、実際にはこれらのファイルは、リモートのサービスで提供が行われています。

  • データファイル : ページサーバー
  • ログファイル : ログサービス

image

これは「ストレージをスケールアウト型のマイクロサービスとして構築した」というようにも言われています。
このアーキテクチャにより、SQL Server を稼働させているサーバー自体には、永続的なデータを持たせることはなくなり、各ファイルの役割をホストしているサーバーにディスクに関しての処理をオフロードすることができるようになります。

プライマリサーバーで、データベースのファイルの存在が確認できます。
しかし、これらのファイルについては、I/O スタックが仮想化されており、実際のファイルを抽象化して取り扱われています。

この抽象化により、SQL Server のコアコンポーネントを大きく変更することなく、従来のモノリシック型のようなデータベースと同様の処理が実現できるようになっています。

 

■Hyperscale のアーキテクチャ

それでは、Hyperscale のアーキテクチャを見ていきましょう。

Hypwerscale は次の 4 つのレイヤーで構成されます。

  1. コンピューティングノード
  2. ページサーバー
  3. ログサービス
  4. Azure Storage

Azure Storage についてはページサーバーとログサーバーのバックエンドで使用されており、本投稿では、次のレイヤーとしてみていきたいと思います。

    1. コンピューティングノード
    2. ページサーバー  + Azure Storage
    3. ログサービス  + Azure Storage

 

■コンピューティングノード

コンピューティングノードの 2 種類のロール

コンピューティングノードについては、次の 2 種類のロールがあります。

  • プライマリノード (書き込み / 読み取り)
  • セカンダリノード (読み取り専用)

各ノードの役割については、従来の SQL Database と同様です。
Hyperscale はマルチマスターではないため、書き込みができるノードは 1 台に限定されています。

プライマリとは別に現時点では最大で 4 台のセカンダリを設定できるようになっており、

  • 1 台のプライマリ
  • 4 台のセカンダリ

の合計 5 ノードの構成が取れるようになっています。
(最大では 15台の読み取りスケールとなっているため、今後台数が増加される可能性があると思います)

 

Resilient Buffer Pool Extension

Hyperscale のコンピューティングノードの特徴の一つには、「Resilient Buffer Pool Extension」(RBPE) の存在があります。

SQL Server 2012 では、バッファプールからキャッシュアウトされるデータを SSD に配置するという Buffer Pool Extension (BPE) という機能が追加されました。

これを障害発生時でも回復性のあるように機能拡張したものが Hyperscale に搭載されています。
この機能は、コンピューティングノードとストレージの両方についていますが、コンピューティングノードについてはローカルの SSD が使用されており、高速な I/O 性能が期待できる領域となっています。

Hyperscale の RBPE では、Hekaton (In-Memory OLTP) のテクノロジも使用されており、高速に処理ができるような構成になっているようです。
(この部分は情報が少なくて理解が進んでいないところでもあります)

Hyperscale のアーキテクチャでは、データファイルはリモートのページサーバーに存在しています。
モノリシック構成の環境とは異なり、データファイルへのアクセスはネットワーク経由となります。

image

初回のデータアクセスについては、ネットワーク経由でアクセスを行うことのオーバーヘッドは避けられません。

しかし、BPE があることで、「一度読み取ったデータだが、メモリが不足してキャッシュアウトされたデータ」については、ネットワーク経由のアクセスを防ぐことができます。

通常は、メモリからキャッシュアウトされると、該当のデータはデータファイルから読み込む必要がありますが、BPE がある場合は、データのキャッシュアウトが発生する際には、BPE にウォームバッファとしてキャッシュアウトさせることができるようになります。

image

再度データが必要になった場合はデータファイルから取得するのではなく、BPE から取得することができます。
これにより「データファイルへのアクセスを抑制できる = ページサーバーへのネットワーク経由でのアクセスを抑制できる」ということになります。

できるだけローカルの I/O だけでデータアクセスを実施させることが可能となります。
ページサーバーの RBPEX については、該当のページサーバーで担保しなくてはいけないすべてのデータをカバーする目的にも使用されますが、コンピューティングノードの RBPEX についてはすべてのデータをカバーする目的ではなく、2 次キャッシュとしての利用を目的としています。

 

プライマリとセカンダリのデータ

モノリシック型のデータベースの場合、プライマリとセカンダリが存在する場合は「セカンダリはプライマリのデータのコピー」を持つことになり、同期方法についても「同期」「非同期」のモードが選べるのが一般的ではないでしょうか。

image

各サーバーががローカルのストレージを使用しており「非共有タイプのディスク」を使用し、データのコピーを行うことで、データの同期が行われます。
このタイプの場合、各サーバーにディスクが必要となり、大規模データベースを作成する際のディスクの柔軟性が低下や、新しい読み取りレプリカを作成する際のデータベースのコピー時間などが発生します。

Hyperscale では、データベースは「非共有タイプのディスク」ではなく「共有ディスク」を使用する設計となっています。

これにより、

  • 大規模データベースに対しての柔軟なストレージ構成
  • 読み取りセカンダリを追加する際に、セカンダリ用のデータコピーが不要

というようなメリットがあります。
Hyperscale では次のように、データベースのデータはプライマリ / セカンダリともに同一のページサーバーを参照する (= 共有ディスクのように同一のデータを参照 )ようになります。

ページサーバーを共有ディスクのように使用して同一のデータファイルを参照させる仕組みですね。

image

この構成を見ると、「同一のデータを参照」しているように見えますが、Hyperscale ではページサーバーへの書き込みは「非同期」で行われます。
そのため、プライマリとセカンダリ間では、データの変更量によってはデータの差が発生する可能性があります。
これは FAQ にも記載されており、遅延については次のように記載されています。

プライマリ計算ノードとセカンダリ計算ノードの間の遅延はどれくらいか

ログ生成速度によって異なりますが、トランザクションがプライマリ上でコミットされた時点から、すぐ、または数ミリ秒です。

シングルデータベースの読み取りレプリカについては「AlwaysOn 可用性グループ」の HADR の機能が使用されているため、同一のデータを保持するセカンダリの存在が保証されています。
(セカンダリにコミットができたことにより、トランザクションをコミットさせる仕組みのため)

AlwaysOn の HADR はデータベースエンジンの機能を使用しているので「各ノードがレプリカサーバーの存在を認識している」という、各ノードが密結合な状態となります。

Hyperscale については、この HADR の仕組みは使用しておらず「各ノードはレプリカが存在することを認識していない」という、各ノードが疎結合な状態となっているというような構成の違いがあります。

 

「Hyperscale の読み取りレプリカは非同期モードでデータの同期が行われているため、データ更新時の反映のタイムラグが発生する」ということは覚えておいた方が良いのではないでしょうか。

 

■ページサーバー

ページサーバーは、データベースのデータファイルをホストするサーバーとなります。

image

1 台のページサーバーでは「128GB」のサイズをサポートしているようで、「各データファイルに対して 1 つのページサーバーが存在」という構成となっているようです。

ページサーバーとデータファイルの関係

SQL Server のデータベースでは複数のデータファイルをサポートしています。
Azure SQL Database では、データファイルの構成は自動構成となっているため利用者が構成に関与することはできないのですが、私が検証で使用していた環境では初期は 4 つのデータファイルが存在しており、各ファイルの最大サイズは 128 GB となっていました。

image

1 データファイル (1 ページサーバー) は次のような認識となっているようです。

  • 最大サイズ : 128 GB
  • 自動拡張サイズ : 10 GB

最初から 128GB のファイルを確保しているのではなく、10GB の自動拡張により増加させているような動作となっているようでした。

データベースのファイルサイズが不足すると新規にページサーバーがー追加され、SQL Server としては、128GB のファイルが追加されたように見えているようです。

実際に 250GB 程度のデータを追加した際には、データベースのファイルは次のようになっていました。
サイズが不足する直前ではなく、ある程度の余裕は持たせた状態で順次追加するというような動作となっているようですね。

image

ページサーバーと Azure Storage

ページサーバーでは、Azure Storage が使用されていますが、これには、Premium Storage と Standard Storage が使用されています。

構成としては次のようになるのかと。

image

データファイルの実体については安価だが低速なストレージである「Azure Standard Storage」に配置が行われています。
これとは別に RBPEX が Azure Premium Storage に配置され、回復性のあるバッファプールについては速度が速いストレージが使用されているというような、用途に応じたストレージの使い分けが行われています。

基本的に Azure Standard Storage のファイルにはアクセスは行われず、「RBPEXだけですべてのデータがカバーされる構成」となります。

最初、「なぜページサーバー上のローカルのディスクを使用しないのか?」と思ったのですが、ページサーバー自体の切り替え (故障やバージョンアップ等の要因) が発生した際を考慮するとリモートストレージを使用した構成をとっておく必要がありますね。
ページサーバーの RBPEX は「自ページサーバーが保持しなくてはいけない全データをカバーする」目的がありますので。

コンピューティングノードについては、「2 次キャッシュとしての利用」ですので、この点は考慮する必要はなく、揮発性のローカル SSD が使えるというわけですね。

image

データファイルのバックアップ方法

データファイルは Azure Standard Storage に格納されており、安価にストレージを利用することができる他に「データファイルのアックアップをスナップショットで対応できる」というメリットもあります。

この機能は、Box の SQL Server のデータファイルを Azure Storage に直接配置した際にも使用できる スナップショットバックアップと同様の考え方です。

従来の SQL Database ではデータベースのバックアップはスナップショットではなく、通常の SQL Server のバックアップ機能が用いられていました。
この機能を用いた場合、次のような点を考慮しておく必要がありました。

  • バックアップの取得時に SQL Server の CPU リソースが消費される
  • データベースのバックアップはブロック単位で取得されるため、ディスク読み取りが発生する
  • データベースのサイズがバックアップ時間に与える影響が大きい

Hyperscale は 100TB をサポートすることができる環境のため、DB のバックアップによるリソースの消費や、実際に取得したバックアップを利用する際に使用する時間についても考慮をしておく必要がありました。

スナップショットを使用したバックアップとして実装することで、次のようなメリットが得られるようになっています。

  • バックアップ取得時のリソース消費はストレージ側にオフロードでき、SQL Server のリソース消費に影響を与えない
  • スナップショットバックアップのため、リストアも高速に実行できる

データファイルのアクセス性能

「Hyperscale はシングルデータベースで最速の環境」と思った方もいるのではないでしょうか。
(私は最初そう思っていました)

以下の画像は、SQL Database にデータベースを作成するときのポータルの画面です。

image

現時点の Hyperscale は性能的には、「汎用目的とビジネスクリティカルの中間」に位置する性能になるのではないでしょうか。
(これは、選択肢として真ん中に表示されているからということではありません)

汎用目的の場合、データ / ログに対しての最大 IOPS は 7,000 IOPS であり、ディスクアクセスでは 5~10 ミリ秒の待機時間が想定されています。

ビジネスクリティカルの場合は、データ / ログに対しての最大 IOPS は 200,000 IOPS であり、ディスクアクセスは 1~2 ミリ秒の待機時間が想定されています。

Hyperscale の場合は次のようになります。

  • データ : 200,000 IOPS / 1~2 ミリ秒の待機
  • ログ : 7,000 IOPS / 5~10 ミリ秒の待機

データについてはビジネスクリティカルと同様、ログについては汎用目的と同様の記載になっていますね。
これは、200,000 IOPS を想定している個所についてはローカルディスク、7,000 IOPS を想定している個所はリモートストレージを利用しているためです。

ビジネスクリティカルのサービスモデルのデータベースのファイルはローカルの SSD に格納されており、高速にアクセスができるようになっています。

しかし、Hyperscale は、データファイルやログファイルはマイクロサービス化された環境をネットワークで接続した環境で実現されており、いくつかの操作ではビジネスクリティカルよりオーバーヘッドが発生します。

Hyperscale のデータアクセスだけ抜き出すと次のような構成となります。

image

メモリ上にデータが載っているのであればビジネスクリティカルと変わらない性能だと思います。
それでは、メモリ上にデータが載っていない状態ではどうでしょうか?

該当のデータがコンピューティングノードの RBEX に保持されている場合は、ビジネスクリティカル相当の性能を発揮することができます。

しかし、コンピューティングノードの RBPEX に保持されていない場合はページサーバーの RBPEX にネットワーク経由で取得する必要があります。
このようなアクセスと似たようなものが汎用目的でも使用されており、ページサーバーからのデータ取得については、汎用目的相当の性能となると考えられます。

まとめると次のような形ですね。

  • コンピューティングノードの RBPEX 上のデータアクセス : ビジネスクリティカル相当の性能
  • ページサーバーの RBPEX 上のデータアクセス : 汎用目的相当の性能

 

ログサービス

それでは、最後にログサービスを見ていきましょう。

ログサービスは、デーベースのログファイルの役目を担うものとなります。

image

ログサービスは内部的に複数のレイヤーで構成されています。

image

ログレコードの書き込みとページサーバーへの反映

データベースに更新が行われると、Premium Storage 上の「ランディングゾーン」にログレコードが記録されます。
(現状は 1TB の Premium Storage のようですが、今後 Ultra SSD への対応も検討されているようです)
image

このデータがページサーバーに連携がされることで、各セカンダリでも同様のデータを読むことができるようになります。
この処理を行っているのが「ログプロセス」となります。
この際の処理は「非同期」で行われています。

image

そのため、「プライマリのデータ反映がセカンダリに適用されるのに遅延が発生する可能性がある」ということにつながっています。

ログプロセスは、ログレコードのアーカイブを長期保存するために、Standard Stoarge にログの書き込みを行い耐障害性と回復性を高めています。

image

ログレコードのセカンダリへの反映

ログサービスは上記の他にも更新のレコードをセカンダリに反映する役割もあります。

image

AlwaysOn の場合、この際の変更がバッファキャッシュにも適用されて直近で更新されたデータはセカンダリでもメモリ上に保持されていたはずなのですが (最近使っていないから忘れてきています…)、Hyperscale の場合は考え方が少し異なっているようで鵜s。

論文の方の記載になるのですが、現状の Hyperscale のログレコードの適用は、「キャッシュされていないページを含むログレコードは無視される」というような動作となっており、セカンダリのメモリ上に保持されていないデータの適用については行われないようです。

このような動作になると「直近で更新されたデータがメモリ上に保持されていない可能性がある」のではないでしょうか。
読み取りのワークロードでセカンダリを使う際には、「どのデータがメモリに乗っているのか?」という動作は意識しておくと初回読み取り性能の劣化を防ぐ一助になるのではないでしょうか。

 

冒頭で紹介したドキュメントでは、さらに細かな内容が解説されているのですが、全体をざっくりと読んだ中で、Hyperscale を取り扱うに際して、最初に覚えておいた方が良い内容としてはこの辺なのかなと思いました。

Written by masayuki.ozawa

6月 2nd, 2019 at 6:39 pm

Leave a Reply

*