ゼロからのデータベース関係インフラ構造拡張ガイド

この記事では、データベース関係インフラ構造の問題で悩んでいるインフラエンジニアの方に少しでも参考になるように、私の長年の経験をまとめて、実際の業務に基づいた記事にしたいと思う。

ネットサービス企業のインフラエンジニアにとって、データベース、ネットワーク、プライベートクラウド（OpenStackなど）、ストレージシステム（ceph、OpenStack swift、Hadoopなど）、この4つものの問題解決が、インフラエンジニアの仕事内容の8割をほぼ埋めている。しかし、通常にはこの4つものはほとんど緊密な関係。だから大規模プロジェクトの経験がないのインフラエンジニアは問題が発生すると圧倒されてしまうことが多いだ。

確かに、全部AWSなどのクラウドを使いれば、この4つものの問題は心配ないですが、逆に考えれば、もし全部のサビースはAWSなどのクラウドでホストしっている、じゃこの会社は本当にインフラエンジニアを必要かなあ？

今回は、これまで私の実務経験をもとに、初期段階から超大規模までのWebサービスのデータベース関連のパフォーマンスを向上させるための拡張方法を簡単に説明する。

じゃ、まず初期段階の定義は何だ？**今回の例は、初めからのECサイト。使うものはLNMP（Linux、Nginx、MySQL、PHP）だ、そしてただ１つのVPSを使っている。**これが今度の例の初期段階の定義だ。

**記事中のMySQLは、どのようなの関係型データベースでもよいことにあらかじめ注意してください。 例えば、PostgreSQL、MariaDB、Perconaなど。 関係型データベースの原理はほとんど同じなので、すべての操作は代替案を見つけることができる。**

じゃ、ここから成長パスを始めましょう。

------------------------------

# 1.最適化

プロジェクトの初期段階では、データベースのパフォーマンスが低下すると、通常、データベースが最初に最適化される。

最適化を行うの方向性はいくつかある：

------------------------------

**1. データベースの設定パラメータを最適化する**

MySQLに内蔵されている統計分析機能を使って、データベースの使用状況を把握することができる。 状況に応じて、データベースを最適化するために異なるパラメータを調整することができる。

**2. クエリインデックスの最適化**

データベースクエリのパフォーマンスが低い場合は、クエリインデックスがビジネスクエリをカバーしていないことが原因である可能性がある。 このとき、クエリを効率化するためにクエリインデックスを調整する必要がある。

**3. SQLクエリコマンドの最適化**

データベースのクエリパフォーマンスが低すぎることがわかった場合、MySQLの低速クエリログ関数を有効にして、低速すぎるSQLコマンドを記録できる。 これらの記録された低速クエリSQLコマンドを分析することにより、基本的に、ほとんどのSQLクエリコマンドに深刻な問題があることがわかる。 その時、これらのSQLクエリコマンドを変更または書き直す必要がある。

------------------------------

上記の最適化の後、データベースのパフォーマンスは通常わずかに改善されます。 基本的に、パフォーマンスの向上は10％を超えることはない。

ただし、最適化した後、データベースのパフォーマンスが10％以上向上していることがわかった場合。 データベースのパフォーマンスを大幅に向上させるこの種の最適化操作は、最適化とは言えない。正確には、これは間違ったデータベース設定の修復です。こんな状況れは一つの事実を証明した、前のデータベース設定きっとエラーがある。

------------------------------

# 2. スケールアップ（Scale-up）

先のデータベース最適化操作以降、あまり効果がないことがきっとわかるはずだ。

これはもちろんだ。データベースの設定が正しい場合、最適化によってパフォーマンスが大幅に向上する可能性はほとんど不可能だ。

これから、データベースのパフォーマンスを向上させる方法を真剣に検討する必要だ。

この状況で、最初に思い浮かぶのが「スケールアップ」なの方法だ。

データベースの「スケールアップ」には2つの方法がある：

------------------------------

**1. 「Webサイト」と「データベース」は別々のサーバーを分離する**

![Snipaste_2020-10-07_02-31-35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668967/d50dc4e2-84a2-faf6-6c0d-4cfac8165463.png)

この方法の原理は、データベースを個別に分離し、データベースだけにサーバーの処理リソースを使ってこと、データベースのパフォーマンスを向上させるという目的を達成することです。

このようにして、Webアプリケーションサーバーはネットワークを介してデータベースサーバーに接続される。Webアプリケーションは内部ネットワークを介してデータベースサーバーに接続することをお勧めする。 1つは、この接続によってセキュリティ上の問題が発生しないこと、もう1つは、接続の遅延を最小限に抑えることだ。

------------------------------

**2. データベースサーバーのハードウェアをアップグレードする**

分離する以降、データベースのパフォーマンスはボトルネックに達した。 この時、データベースサーバーのハードウェア構成のアップグレードを検討する必要だ。

データベースはサーバーのCPU周波数パフォーマンスとディスクの読み取りおよび書き込み速度に大きく依存しているためだから、ハードウェアをアップグレードするときは、高周波のCPUと、読み取りおよび書き込みのパフォーマンスが良好なSSDを選択する必要だ。特にSSDは、できればNvmeのSSDを使ってがいい、予算が問題ないなら、インテルの「Optane SSD」に考えしてくれ。でも予算が大問題なら、一般なSSDにRAID１０技術を使ってもいい（何故RAID１０？安全のためだ）。

------------------------------

以上は「スケールアップ」の2つな方法だ。暫くにぐっすり眠れってきるね。

------------------------------

# 3. スケールアウト（Scale out）

プロジェクト事業が大きくなるにつれ、データベースのパフォーマンスが再びボトルネックになってきた。しかし、データベースサーバーを現在利用可能な最高のハードウェアにアップグレードしたため、データベースのパフォーマンスを向上させるためにハードウェアをアップグレードすることができなくなってしまいました。これはどうしようかな？

この時、データベースの「スケールアウト」を検討する必要だ。

「スケールアウト」のアップグレードパスここから始まるよ：

------------------------------

**1. 「読み」と「書き」の分離**

![Snipaste_2020-10-07_05-23-46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668967/bfb100a7-13df-49d3-8666-31a186119f92.png)

「読み書き分離」は、データベースの「スケールアウト」の第一歩です。 このデータベースインフラ構造は、MySQLの同期レプリケーション機能を利用して複数の「スレーブ」をレプリケートし、「読み書き分離」に「MySQL Router」などのデータベース・ミドルウェアを使用している。「MySQL Router」は、ロードバランシングを利用して読み取りタスクを各「スレーブ」に分散させることで、データベースの読み取り制御を向上させている。 "MySQL Routerはロードバランシングを利用して各スレーブにリードを分散させ、データベースへのリードを増加させる。 パフォーマンス。 一般的なECサイトでは、データベースへの読む操作は書き操作より何倍以上の数量がある。 これば、読み操作に必要な圧力をすべて「スレーブ」にシフトさせった。でも書き操作はすべてに「マスター」を書いた。

------------------------------

**2. マスターとマスター同期**

![Snipaste_2020-10-07_06-24-59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668967/7731ce7f-0c82-2391-8e69-4f4fcaa7fe7a.png)

「マスターとマスター同期」では、先の「読み書き分離」に比べて冗長性の高い「マスター」が追加されている。 このデータベースインフラ構造により、「読み書き分離」のデータベースはより安全になります。 しかし、このデータベースインフラ構造ではパフォーマンスの向上は見込めません。 複数の「マスター」を使用しても、データベースの書き込み性能は向上しない。

このタイプのデータベース構造では、「MySQLDump」のようなバックアップ操作が必要な場合は、バックアップ専用の「スレーブ」を開くことで、メインデータベースの処理リソースを使わないようにしている。

------------------------------

**3. さらなる分離**

![Snipaste_2020-10-07_06-47-19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668967/43295111-7109-6b58-e750-d91c53f7a377.png)

ある程度の時間が経つと、データベースのパフォーマンスが再びボトルネックになってきた。

データベースの読み込みパフォーマンスの問題を解決するために「スレーブ」の数を増やすことはいつでもできますが、それは持続可能な解決策ではない。

機能を分離は必要がある。例えば、リソースを大量に消費する全文検索は「ElasticSearch」を使えば可能だ。 例えば、「注文詳細記録」の内容を「NoSQL」を使って保存することもできる。同時に、データベースのキャッシュを分離し、別のキャッシングシステムを使ってデータベースのデータをキャッシュしている。これだけ多くの新機能を同時に管理するためには、データ関連業務のコントロールセンターとして専用の「データ管理バックエンド」を開発し、データベースへの書き込みのプレッシャーを軽減するために「タスクキュー」機能を導入する必要だ。

このようなデータベースインフラ構造により、ハードウェアリソースをより合理的に使用し、より高い全体的なパフォーマンスを提供することができる。

------------------------------

**4. シャーディング（Sharding）**

![Snipaste_2020-10-07_07-39-32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668967/c8afb362-b636-4a66-0203-4bc53b47ce1c.png)

「シャーディング」とは、データベース内のデータを分割し、複数のデータベースに保存するの手段だ。それもデータベースの書き込み性能を向上させる唯一の手段だ。

「シャーディング」のタイプは２つがある、「スケールアップ·シャーディング」と「スケールアウト·シャーディング」だ。

------------------------------

**スケールアップ·シャーディング：**

異なるデータテーブルを異なるデータベースに分割しする。

**スケールアウト·シャーディング：**

巨大なデータテーブルを複数の部分に分割し、それらを異なるデータベースに保存する。

------------------------------

これは、「オブジェクトストレージ」という概念に少し似ている。 そのため、どのデータベースにデータを格納したいかを知るためには、この目的のために別のデータベースを作成しなければならない。 同時に、「データ管理バックエンド」は、データを正しく読み込めるように適宜変更する必要だ。

上の写真から、これは巨大なデータベースシステムになることがわかるんだ。だから、このような巨大なシステムを維持するためには、インフラストラクチャエンジニアはかなりの労力を費やす必要だ。

予算が十分余裕であれば、今後のパフォーマンスのボトルネックに対応するために、このデータベースインフラ構造を拡張し続けることができる。

------------------------------

#4. 結論

結論から言うと、このデータベースインフラ構造のスケーリングはそれほど難しくない。 しかし、悪循環に巻き込まれているのも事実で、このデータベースシステムを支えるためには多くのサーバーリソースを費やす必要があるで、そしてこのデータベースシステムで使用されるサーバーの数は常に拡大していくことがわかるんだ。

でも、企業のデータベースシステムがそこまで大きくなると、収益と比較しても大きな意味があるんですよね。 そのため、企業は通常、「NewSQL」に置き換えたり、より効率性を追求して独自のデータベースシステムを開発したりすることを選択する。

これが役に立つといいですね。以上です。