Web開発者のための大規模サービス技術入門を読んだ
会社の本棚にあったものを読むことにした。
業務ではWebフロントに注力していて、触るとしてもnginxやCDNまわりなのでサービス負荷について考える基準が欲しかったことがモチベーション。
少し古い本なので多少内容が陳腐化している箇所もあったものの、今でも使える基本的な知識や考え方について解説されている。(やむを得ないが)書籍中に出てくるコードはほぼPerlなので読んでなんとなく内容を察する程度で精一杯だった。
OSキャッシュやスケーリングの考え方はあまり詳しく知らなかったところなので良かった。業務外でサーバーを立てる時もスペックは割と適当だったりするので、この辺りの考え方を体得できると業務にも役立てることが出来そう。OSキャッシュの辺りは特に、言われてみれば当たり前だが今までさほど気にしたこともなかった。普段はブラウザ全体のメモリ消費量をなんとなく気にする程度なのだが、アプリケーションのパフォーマンスの観点でもメモリ消費量を気にする癖をつけたい。モニタリングが手軽に出来れば良いのだろうか。
DBまわりも通り一遍というかクエリの書き方を知っている程度なので、サービスに落とし込む際にどういったことを考えるかを知れてよかった。マスタースレーブ構成のクラスタにおいて、マスター間の遅延について考えたこともなかったので新鮮だった。また、これも初歩的な話だがストレージエンジンについて今までほぼシカトしてきていたので知ることができてよかった。
また、アルゴリズムにも興味があった。学生時代に講義で触った記憶はあるものの、ほぼ忘れ去っているからだ。せめてクイックソートくらいは諳んじて書けるようにしたい。結果、書籍中では具体的なアルゴリズムに踏み込んではいなかったが、きっかけにはなった。実践するには競技プログラミングあたりに踏み込むことになるのだろうか。
領域外の知識を吸収する足がかりに出来そうなので、定期的に読み返しておきたい。
以下読書メモ。
オリエンテーション
- スケールアウト時の課題
- ロードバランシング
- データの同期
- ネットワークレイテンシ
- 大規模データ量への対処
- ディスク、メモリ、キャッシュメモリ、CPUの順で速度差がある
- データが小さいうちは処理をメモリで行えるが、大規模になるとそうはいかない
- いかにデータを小さく持つか、複数サーバーに分散させるか、必要なデータを最小限の回数で読み取るか
大規模データ処理入門
- 大規模データとは何か
- 大規模すぎてメモリで処理できない
- メモリはディスクの105 ~ 106倍早い
- SSDは高速だが、バスの性能差故にメモリほどではない
- 負荷の種類
- CPU負荷
- I/O負荷
- ボトルネックを調べるには
- CPU負荷のスケーリングはサーバー台数を増やす
- DBなどI/Oの場合は、データ同期の観点から分散が難しい
OSのキャッシュと分散
- ページ: OSが物理メモリを確保/管理する単位、仮想メモリの最小単位
- プロセスは仮想メモリにしかアクセスできず、ディスクに直接アクセス出来ない
- そのプロセスがアクセス済みになったデータもメモリに残しておく、これがページキャッシュ
- 一度ディスクにアクセスすると、その後のアクセスが早くなる
- LRU: Least Recently Used、一番古いものを破棄して新しいものを残す
- Linuxはメモリがあいていればディスクをキャッシュし続ける
- メモリを増やす = I/O負荷軽減
- キャッシュがI/O対策の基本
- 小さければメモリに載せきれる
- データをキャッシュしきれない規模になったら、複数サーバーでのスケールを考える
- CPUリソース(APIサーバー)が必要な場合は単純に増やせる
- DBの場合は局所性が絡んでくる
- メモリの増設ポイント
- キャッシュ容量と、アプリケーションが扱う有効なデータ量を比較する
- 局所性対策
- アクセスパターンを考慮して分散させて、キャッシュできない領域をなくす
- パーティショニングで実現することが多い
- 負荷分散の学習のためには、OSの動作原理を知ると良い
DBのスケールアウト戦略
- インデックスを正しく運用する
- カラムの型が何で、どれくらいのバイト数で、全体通すとどれくらいのサイズになるのか計算する
- B+木
- O(n) to O(log n)
- MySQLでは、where, order by , group byに指定されたカラムに対してインデックスが使われる
- 明示的に作用したインデックス、プライマリーキー、UNIQUE制約がインデックスとして作用する
- MySQLにおいては、複数カラムがインデックス利用の対象になった場合には、複合インデックスを使う必要がある
- 単一のインデックスの場合は、どちらかのインデックスのみが使われる
- explainコマンドで、インデックスが効いているかどうか確認できる
- レプリケーション
- マスタースレーブ
- マスターが更新系、スレーブが参照系
- 参照系はスケールするが、更新系はスケールさせない
- どうしても更新系をスケールさせる際は、テーブル分割でテーブルサイズを小さくする
- もしくはKVSを使う、RDBMSではなくする
- ポーリング
- マスタースレーブ
- MySQLでは、異なるサーバーにあるテーブルをJOINできない
- クエリを分割して対応する方が良い
- テーブル同士が密結合であれば、同じサーバーにおいてしまう方が良い
- パーティショニングのデメリット
- 運用が複雑になる
- 故障率が上がる
- 冗長化を考えるとマスター1スレーブ3の4台1セットにすると良い
- 故障時のデータコピーのことを考える
- パーティショニングはあくまで切り札として扱う方が良い
大規模データ処理[実践]入門
アルゴリズムの実用化
- 広義のアルゴリズム
- 実装の仕組みなど
- 狭義のアルゴリズム
- 定義された計算問題に対して、定義された計算を行うもの
- 対数的な計算量のアルゴリズムを選びたい
- アルゴリズムとデータ構造はセット
- (私見)アルゴリズムを知っているかどうか、が重要な気がする
- アルゴリズムを用いる場合は、テストファーストで開発を進めると良い
大規模データ処理を支えるサーバー/インフラ入門
- エンタープライズでは信頼性が最重要視され、またトランザクションが多用される傾向にある
- webとエンタープライズではインフラにおける重要ポイントが異なる
- クラウドのメリデメ
- スケーラビリティ
- 各クラウドサービスの独自仕様に対応
- オンプレ
- サーバー/インフラ構成の自由度が高い
スケーラビリティの確保に必要な考え方
- 多くのサービスはサーバー一台で動く
- 4core CPU 8GB: 100万PV/月
- 4core CPU 32GB: 200万PV/月
- 負荷を測るための項目
- ロードアベレージ
- それらのプロセスがいつでも動ける状態なのにCPUが未割り当てで、待ち状態にあるプロセスの平均値
- メモリの割当状態
- ロードアベレージ
- 用途ごとのチューニング
- レスポンスタイム、処理数など何に注力するのか
- 用途が増え、細分化すると管理や異常検知が大変
- だからkubeが人気になったんだよなあ
冗長性の確保、システムの安定化
- 単一故障点の除去
- APサーバーは、台数を並べるのが基本
- ロードバランサのフェイルオーバー、フェイルオーバー
- ロードバランサによるAPサーバーのヘルスチェック
- 落ちたら外して、復帰したら戻す
- ロードバランサのフェイルオーバー、フェイルオーバー
- サーバーが止まる理由は様々
- 人為的な理由
- 物理的な故障
- メモリ異常
- DBサーバー
- マスタースレーブ方式で、一台二台落ちても大丈夫にする
- マスターの冗長化にはマルチマスタ方式を用いる
- 双方が双方のスレーブである
- 片方への更新が、もう片方にも伝搬する
- ミリ秒単位の遅延は避けられない(割り切るか、どうか
- マルチマスタ
- ストレージサーバー
- MogileFS: 分散ストレージサーバー
- システムの安定化
Webサービスとネットワーク
- サービスの成長とネットワークの分岐点
いまどきのWebサービス構築に求められる実践技術
- ジョブキューシステム
- リクエストを非同期にしたい
- 構成要素
- クライアント
- ジョブを投入するもの
- ジョブキュー
- ジョブを蓄えるキュー
- ワーカー
- ジョブキューから未実行のジョブを取り出して実行
- クライアント
- よさそう
- ストレージの選択
- 適切なストレージを選択することは難しい
- アプリケーションからストレージを参照する際のアクセスパターン
- 平均サイズ
- 最大サイズ
- 新規追加頻度
- 更新頻度
- 削除頻度
- 参照頻度
- ストレージの種類
- RDBMS
- 分散key-valueストア
- memcached
- メモリ上で動作
- キャッシュとして使う
- redisと比べて、パフォーマンスに大きく差があるわけではない
- redisに出来て、memcachedに出来ないこと
- データの永続化(ただし永続化設定するとその精密さに応じてパフォーマンスは下がる)
- master/slave構成
- 暗号化
- ソート
- https://qiita.com/robitan/items/2e7f599c4cb1d65f3286
- memcached
- キャッシュシステム
- フォワードプロキシ
- クライアントが外部のサーバー・ネットワークに接続する際に挟むプロキシ
- リバースプロキシ
- 外部のクライアントが内部のサーバー・ネットワークに接続する際に挟むプロキシ
- これらのプロキシでは、リクエストをキャッシュしておくことが出来る
- キャッシュサーバーのメリット
- 平常時に、APサーバーへのリクエストを軽減することが出来る
- サーバーの台数削減に繋がる
- アクセス増加時には、負荷増大によるシステム全体のダウンを予防することが出来る
- アクセスが集中しているコンテンツをキャッシュして返す
- 平常時に、APサーバーへのリクエストを軽減することが出来る
- 分散、冗長化も効果的
- 容量が大きいファイルなどをキャッシュする場合は、キャッシュサーバーを二重化すると良い
- サーバー起動時にはキャッシュが全然ないから注意
- activeにする前に、ウォームアップをしてキャッシュを溜めておこう
- Squid
- リバースプロキシキャッシュサーバー
- 結構歴史がある
- 代替にはnginx, varnishなど。。。
- Varnish
- フォワードプロキシ
- 計算クラスタ
- Hadoop
- Redshift
- 最近のトレンドは。。。?
- BiqQuery?