Alibaba CloudのPolarDBの徹底分析(1)_アーキテクチャ編

# 1. PolarDBとは
PolarDBは、Alibaba Cloud社が開発した次世代リレーショナルデータベースで、`MySQL,PostgreSQLと100％互換性`があるため、これまでMySQLあるいはPostgreSQLを使っていたアプリケーションは、PolarDBに移行するには1行もコードを変更する必要がありません。
一言いうと、Aibaba cloud版のAuroraです。

:::note info
内部構成や課金などについてPolarDBとAuroraは異なる点もたくさんありまして、両者の比較は別の記事でまとめますので、ご期待ください。
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/19944d89-02b5-8643-0844-a6301275b34e.png)



# 2. アーキテクチャ
## RDSのアーキテクチャ
先にRDSのアーキテクチャを見てみましょう。
RDSのアーキテクチャはVMのECSにMySQLやPostgreSQLを時前でインストールする場合と大差ないと考えても過言ではありません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/527d2b5a-9e4b-f695-4f4f-2d6a673f2c25.png)


## PolarDBのアーキテクチャ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/4449c0f9-21fa-07da-01e5-93e314a4f7d3.png)

## クラスター構成
PolarDBに`クラスター`という概念がありまして、PolarDBの管理単位になります。一つの`primayノード`と複数の`read-onlyノード`、そして`PolarStore`という分散ストレージから構成される`マルチノードクラスター`で操作します。

::: note info
`ノード`は`インスタンス`と呼ばれている場合もありまして、今記事は`ノード`という言葉に統一します。
:::
- Pimaryノード：
    - 一つのクラスターには必ず一つのprimaryノードがあり、しかも一つしかありません。
    - 読み書き両方可能であり、`マスターノード`と呼ばれる場合もあります。
- read-onlyノード： 
    - 読み取りしかできないノード
    - 0~15個まで
- PolarStore:
    - 同じクラスター内すべてのノード間でシェアされているストレージであり、データ自体はこちらで保存されています。

- 内部プロキシ層による`読み書き自動分離`
PolarDBは、内部プロキシ層(built-inのproxyであり、userから意識する必要もない)を通して外部に提供される。
つまり、すべてのアプリケーションは、特定のノードにアクセスする前にプロキシ層を通過します。 
また、SQLを解析し、書き込み処理（Update、Insert、Delete、DDLなど）をWriterノードに送り、読み込み処理（Selectなど）を複数のReaderノードにバランスよく振り分けることができ、これを`読み書き自動分離`とも呼ばれています。


## データベースエンドポイントについて
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/3a84d00b-783d-82de-2d7c-1379088035d9.png)


- PolarDBでは、デフォルトで`cluster endpoint`と`primary endpoint`の2つのデータベースendpointが利用できます。
- 必要があれば、手動で`custom endpoint`を作成し、どのノードを使いたいのかも自由に選択できます。
1. cluster endpoint：
    - すべてのノードにアクセスできるエンドポイント
    - 書き込み処理は自動的にpimaryノードに振り分けられ、読み取り処理は自動的に全部のノードに分散的に振り分けられるという`読み書き自動分離`の機能を持っているため、ほとんどの場合はこちらを利用することが推奨されています。 
2. primary endpoint：
    - 常にprimaryノードに接続するエンドポイント
    - フェイルオーバー時の動き：primaryノードが何か不具合によってクラッシュしてしまう場合は、一つのread-onlyノードが自動的に選ばれて、30秒以内にprimaryノードに昇格される。そして、プライマリーエンドポイントの指し先は自動的に新しいprimaryノードに切り替えられる。
3. custom endpoint：
    - OLTP(Online Transaction Processing )の処理と同じデータベースを利用し、OLAP(Online Analytical Processing、つまり読み取り負荷の高い分析用のアプリケーション)処理もしたい場合は、メインのOLTP処理のパフォマンスに影響を与えないように専用の`custom endpoint`を作成し、OLAP専用のread-onlyノードに紐づくというやり方はよくあります。
    - 必要に応じて、複数custom endpointが自由に作られます。

https://www.alibabacloud.com/help/ja/polardb-for-mysql/latest/configure-polarproxy#concept-186667

# RDSとの違い
PolarDBは、MySQLと同じように利用できることに加え、従来のMySQLデータベースにはない以下のような利点があります。

## ストレージ容量
- RDS：
    - `購入時にストレージ容量を指定`する必要があります。使い切れていなくても指定したストレージ容量分が課金されることにになります。
    - ストレージタイプによって上限が異なりますが、`最大32TB`まで使えます。
    - 1台のストレージ容量の上限を超えていた時に、複雑なシャーディングの仕組みを検討させるをえないことになってしまいます。
- PolarDB：
    - 購入時に容量を指定する必要がなく、データの増加に合わせてオンラインで自動的に拡張されます。使用量に応じて課金され、`本当に使った分だけ課金`され、課金周期は1時間となっています。
    - クラスターのスペックによって上限が異なり、`最大100T`まで使えます。
    - 1台のマシンの容量が上限でシャーディングを行うために複数のMySQLインスタンスを購入したり、ライブラリやテーブルの分割を検討する必要さえなく、アプリケーション開発の簡素化と運用・保守の負担軽減を実現します。

※PolarDBの最大ストレージ容量：

https://www.alibabacloud.com/help/en/polardb-for-mysql/latest/specifications-of-compute-nodes#concept-2035312


## コストパフォーマンス
- RDS：
    - `各インスタンスごとにストレージを持っている`ため、read-onlyのインスタンスが増えれば増えるほどストレージ料金がかかります。
- PolarDB：
    - `共有ストレージ`のアーキテクチャであり、複数ノードはストレージの1シェア分しか課金されないので、読み取り専用ノードが多ければ多いほどコストパフォーマンスが高くなります。

## スケールイン・スケールアウトとスケールアップ・スケールダウンのスピード
- RDS：
    - レプリカごとにインスタンスとストレージを持っているアーキテクチャです。スケールアウトする時にはバックアップから新しいリードレプリカインスタンスを起動してから、binlogを取得し、バックアップ取ってからその時点までのすべての処理(create,update,deleteのクエリ)を順次的に実行する必要があります。
    - リードレプリカが使えるまでの時間はやはり`データ量に応じて、数時間かかる`場合も非常に多いです。
- PolarDB：
    - ノード間でストレージを共有するため、`5分程度`リードレプリカが使えることになります。
    - 同様にインスタンスのスペックを上げたり下げたりすることもRDSはデータ量によりますが、PolaDBはデータ量によらず`5分程度`できることです。


## 読み込みの一貫性
- RDS：
    - primary instanceからread-only instanceへのレプリケーションは非同期であり、準同期であっても100％強力な同期を実現する方法はありません。特にprimary instance側で大量の書き込み処理が発生する時にレプリケーションによる遅延が発生し、書き込み処理を実施した直後でデータを取得しようとすると、古いデータを取得してしまうという現象が発生しうる、クエリの一貫性が保証されません。
つまり、以下の処理のように、update処理を実行した直後で、update済みのはずのデータをselectしてみると、古いデータが返される可能性があります。
        ```
        connection.query
        {
        UPDATE user set name = 'Dennis' WHERE id=1;
        commit;
        SELECT name FROM user WHERE id=1;
        }
        ```
- PolarDB：
    - クラスタの読み出しと書き込みのアドレスが分かれているため、データを読み出す際にLSN（Log Sequence Number）を使用してグローバルな一貫性を確保し、primaryとread-onlyのレプリケーションレイテンシーに起因するデータの不整合の問題を回避することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/89183c6f-d8fc-67fc-68f3-54cbd8cbd302.png)


## レプリケーションによるレイテンシー
- RDS：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/ddf66c9e-8c16-6e0f-3b97-999474e6b4f9.png)

    - `binlog(論理ログ)`によるレプリケーションです。
    - MySQLの負荷が低い場合は5秒以内に制御できますが、負荷が非常に高い場合、特に大きなテーブルに対するDDL（フィールドの追加など）や一括挿入を行う場合は、レイテンシが非常に大きくなる可能性が高いです。
   
- PolarDB：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28664/74feea45-b063-16c8-baa8-c7a84a13b154.png)

    - Binlogベースの論理レプリケーションの代わりに`Redoログ`の`物理レプリケーション`を使用することで、`ミリ`秒のレイテンシーまで実現できています。
    - インデックスやフィールドの追加など、大規模なテーブルのDDL操作でも、低いレイテンシーが担保できる。

## ロックフリーのバックアップ
ストレージ層でスナップショットを利用することで、データサイズ2Tのデータベースを60秒でバックアップすることができます。 
バックアップ処理は、データベースをロックする必要がなく、アプリケーションにほとんど影響を与えず、24時間いつでもバックアップが可能です。

## 複雑なSQLクエリの高速化
- 内蔵の並列クエリーエンジンは、実行に1分以上かかる複雑な分析用SQLを大幅に高速化できる。