台数を増やすと何が起きるか
読了目安 約4分
リソースを増やしたときの効率を測り、単一マシンだから速い手法がスケールを塞ぐ仕組みを見ます。
この章の目次
サーバーを 3 台に増やしても、捌ける量は 3 倍になりません。 どれだけ近づいたかを測ると、次に直す場所が決まります。
効率を測る
リソースを p 個に増やしたときの容量を、1 個のときと比べます。
- :リソースの個数(ここではアプリの台数)
- :リソースが 個のときに捌ける件数
- :相対容量。1 個のときの何倍か
- :効率。理想の線形に対する達成率で、1 なら理想的
| アプリの台数 | 捌けた件数/秒 | ||
|---|---|---|---|
| 1 | 1,000 | 1.0 | 1.00 |
| 2 | 1,800 | 1.8 | 0.90 |
| 3 | 2,400 | 2.4 | 0.80 |
この割り算の出番は、次の 1 台を頼む前です。 が低い理由を直さないまま 3 台目を足しても、同じ理由で無駄になります。
効率 0.80、アプリの CPU は余裕、データベースは飽和。 ここまで分かれば、次に分けるべきものを選べます。
増やしても伸びないのは共有部分のせい
伸びるのは、増やしたリソースがボトルネックだった場合だけです。 アプリを 3 台にしても、全台が同じデータベースを見ているなら、データベースの容量は増えていません。
共有しているリソースのサービス需要は、台数に関係なく一定です。
別のマシンに分けると通信が遅くなる
アプリとデータベースを別のマシンに分けると、両者の間の通信がネットワーク越しになります。 コンピュータにおけるデータの操作とコスト感 のとおり、同じマシンの中の往復は数十マイクロ秒、マシンをまたぐと 200 マイクロ秒前後です。
クエリ 1 本ごとにこの往復が 1 回付くので、本数が多い処理ほど遅くなり方が大きくなります。 1 文ずつデータを流し込む初期化処理は、同じマシンなら十分速くても、分けた瞬間に往復の合計だけで規定時間を超えます。
飽和していないリソースを分けても、容量は増えず、通信が遅くなるだけです。 台数を増やす前に、いま何が飽和しているかを確定させるのはこのためです。
1 台に載っているあいだだけ使える高速化
アプリとデータベースが 1 台に載っているあいだだけ、確実に速くなる手があります。 ただし、あとでマシンを分けるとき、それ自体が障害になります。
Unix ドメインソケットは、同じマシンのプロセス同士をファイル経由でつなぐ通信方法です。 ネットワークを通らないぶん速くなります。
プロセス内のキャッシュは、アプリケーション自身のメモリに結果を覚えておく方法です。 アプリを 2 台に増やすと、片方で更新した内容がもう片方に伝わらず、古い値を返します。
これを避けるのが、データをどこに置くか の共有のキャッシュサーバーです。
| 手法 | 単一マシンでの効果 | 増やしたときの問題 |
|---|---|---|
| Unix ドメインソケット | 確実に速い | 分けたら使えない |
| プロセス内キャッシュ | 最も速い | サーバーごとに中身がずれる |
| 共有のキャッシュサーバー | 往復が 1 回増える | 台数を増やしても一貫する |
1 台で終わらせるなら、上の 2 つが正解です。 分ける見込みがあるなら、分けられなくなる手を入れる前に、先に分けます。 逆だと、終盤に、速くするために入れたものを剥がすところから始まります。
キャッシュは新しい直列区間を作る
共有のキャッシュサーバーにも、新しい問題が付いてきます。 覚えた値が消えた瞬間に全アプリが同時に作り直しにいくと、データベースへの問い合わせが一斉に走ります。
さらに、古い読み取り結果が後から新しい結果を上書きして、内容が巻き戻ることがあります。 作り直しは 1 つだけが走るようにして、他はその結果を待たせます。 この「待たせる」区間が、次章で扱う直列部分そのものです。
試してみよう
アプリの台数だけを変えて測ったら、次のようになったとします。
| アプリの台数 | 捌けた件数/秒 | データベースの CPU 使用率 |
|---|---|---|
| 1 | 900 | 45% |
| 2 | 1,530 | 77% |
- はいくつですか
- データベースの使用率は、1 件あたりで見るとほぼ一定です。100% に届くのは毎秒何件のときですか
- 3 台目を足すと、何件くらいで頭打ちになりますか
答えを見る
は 0.85。データベースは 1 件あたり約 0.05 パーセントを使うので、100% になるのは毎秒およそ 2,000 件です。3 台にしても 2,000 件の手前で頭打ちになり、しかもその前に待ち時間が伸び始めます。
3 台目を足す前にやることは、データベースの を下げることです。