Wille Faler氏は、 データベースのオフロード、キャッシュの利用、ネットワークトラフィックの最小化といった、スケーラビリティとパフォーマンスのための8つのベストプラクティス を提案している。
1. データベースをオフロードする – できるだけデータベースに近づかないこと。つまり、必要がない限り、データベース接続をオープンしてはいけないし、トランザクションを開始してはいけない、ということだ。
2. キャッシュを利用すると段違い – キャッシュを利用すると、特に読み出しモードでデータベースにアクセスするアプリケーションの場合、データベースをかなりオフロードすることができる。メモリキャッシュはディスクキャッシュよりも望ましく、ディスクキャッシュはネットワーク越しのアクセスやリレーショナルデータベースよりも望ましい。
3. できるだけ粒度の粗いオブジェクトとしてキャッシュする – 粒度の粗いオブジェクトとしてキャッシュすると、「n 個のキャッシュゾーンではなく1つのキャッシュゾーンに問い合わせるだけでよくなり、必要なCPUリソースや時間を節約できる。その上、オブジェクトグラフ全体を取得すると、オブジェクトグラフを自分で組み立てる時間も節約できる。」
4. 一時的な状態を永続的に格納してはいけない – ログインセッションデータのような一時的なデータをデータベースに格納するのは避けること。
“状態の怪物 (state monster)” は危険です。私の経験から言うと、永続的なストレージ(データベースやディスク)に格納するのは、実在する、必要かつ重要な、利用可能なビジネスデータだけにして、それ以外は格納してはいけません。
5. 配置、配置 – 配信するものは配信先の近くに配置しておくこと。ロードバランサ、Webサーバ、アプリケーションサーバ、データベースといたものをすべて経由するのではなく、ロードバランサとWebサーバを経由して CDN からコンテンツを取得する方が高速で、リソースも節約できる。
6. 平行アクセスは限られたリソースに限定する – もし複数のリクエストが同じリソースにアクセスして同じ計算をしているなら、まず最初のリクエストを処理しよう。そして、他のリクエストにはその処理が完了するのを待たせて、その最終結果を再利用する方が望ましい。すべてのスレッドがリソースにアクセスできても、処理が遅くなるだけだろう。
7. ステージ化による非同期処理
非同期性の観点から、1つのプロセスをキューによって個別のステップに分離して、各ステップをワーカースレッドの数を制限して実行しよう。こうすると、スケーラビリティとパフォーマンスが驚くほど改善されることが多いです。
8. ネットワーク越しのやりとりを最小化する – アプリケーションはできるだけリモートでやりとりしないようにすること。ネットワーク越しのやりとりはメモリに比べると、無視できないくらい遅いためだ。
Faler氏の投稿に対して、いくつかコメントが付いている。データベースをオフロードすることについて Steve M. Ciske氏 は次のように注意している。
私はデータベースをオフロードすることについては慎重です。まったく正反対な手段をとり、すべてをアプリケーション層に置いている人を見たことがあります。
Pawe? Stradomski氏 は、リモートにあるメモリキャッシュはローカルにあるディスクキャッシュよりも高速である、と考えており、Faler氏もこれに同意している。
リモートホストにあるメモリに(ネットワーク越しに)キャッシュする方が、ローカルにあるディスクにキャッシュするよりも速いこともあるでしょう。ディスクからシーケンシャルデータを読み出すのは、リモートホスト上のメモリから読み出すのと比べて、およそ3倍以上遅くなります。シーク時間については言うまでもないでしょう。
関連情報: Simon Brown氏は スケーラビリティの原理 という記事を書いている。