『システム設計の面接試験』を読む

これはなに

読むやつです。読むのはこれ。

https://www.amazon.co.jp/dp/4802614063/

どういう構成でシステムを作っていけば良いのか? みたいな情報って、コードレベルだとアーキテクチャの文脈だったりデザインパターンとかで色々議論されてるんだけど、こういうレベルだとなかなかなくて、おれはこれくらいの構成の仕方がずっと知りたくて、読んだ。

第1章 ユーザー数ゼロから数百万人へのスケールアップ

単一サーバーのセットアップ

  • 概要
    • サーバがあって、ユーザーはブラウザやクライアントアプリからアクセスする
  • 感想
    • 分かる。このレベルからやってくれるのありがて〜〜

データベース

  • 概要
    • webアプリケーション用のサーバからデータベース用のサーバを切り出す。
  • 感想
    • これってサーバ分けるとそんな負荷減るのかな
      • トラフィックさばくのってどれくらい大変なんだろう? データベースは忙しそうって思うけど。
  • データベースの選定
    • RDBMSかNoSQLか

スケーリング

  • 種類
    • 垂直スケーリング
      • 単一サーバーのグレードアップ
      • 単純だけど限界があるし単一障害点になっちゃう
    • 水平スケーリング
      • サーバをたくさん増やす
      • 耐障害性もふえてうれしい

ロードバランサー

  • 概要
    • webトラフィックを振り分けるやつ
      • 外部からアクセスされるのがLBだけになるのも嬉しい
    • Webサーバーの水平スケーリングを成り立たせる要素

データベースレプリケーション

  • 概要
    • データベースのコピーを作るやつ
    • DBサーバの水平スケーリングを成り立たせる
  • 詳細
    • マスターは書き込み、コピーはマスターの内容をコピーして読み取りように使う
    • だいたいはマスターが少なくて、コピーは多い(読み込みの方が多いため)
    • メリット: パフォーマンス上がる、信頼性高まる(データロスト)、可用性が高まる
  • 疑問
    • マスターを複数持ちたいときってどうする?
      • 適当なマスターに書き込んで、そこから他のマスターにも反映てかんじか
      • マルチマスターはやっぱ多少複雑っぽい。本書では扱わないとのこと
    • 書き込み系のキャッシュファイルとかそういうデータベースの負荷低めるための工夫はレプリケーションに対応してるの?
      • これとか
      • 何言ってんのかほぼ分からんが、なんとなくいい感じに書き込みを反映させてくれているっぽい
    • これRAIDとかの話とは別ね
      • あれはHDDの話
      • レプリケーション当たり前になったら求められるRAID変わりそう

キャッシュ

  • 概要
    • 頻繁にアクセスされるデータをメモリに置く
  • 詳細
    • WebサーバーとDBサーバーの間にキャッシュ層を挟んで、キャッシュされている場合はDBサーバーにアクセスが行かないようにする
    • 注意点
      • キャッシュが有効かどうかを考える。読み込みが多いシステムは有効
      • 有効期限ポリシーの設定
      • 一貫性(データストアとキャッシュの間の一貫性)
      • 障害の軽減
      • 消去ポリシー
  • 感想
    • CDNの話かとおもったけどキャッシュ全般の話っぽい?

CDN

  • 概要
    • 主に静的コンテンツのキャッシュサービス
  • 注意点
    • コスト
      • CDNへ/からのデータ転送に対して課金される。使用頻度の低いものは外す
      • いちど保管されて使われないままTTLが切れる状況をさけたい
    • TTLの適切な設定
    • CDNフォールバック
      • CDN障害時の動きを整理しとく
    • 有効期限の切れたファイルの無効化
      • CDNのAPIを叩いて無効化
      • オブジェクトのバージョニングをする

ステートレスWeb層

  • 概要
    • Web層の水平スケーリングのために、Web層が状態を持たない(ユーザーの状態データなど)ようにする
    • クッキーとかのはなし???
  • ステートフルアーキテクチャ
    • 複数のサーバーで捌いているときに、ユーザーから特定のサーバーにアクセスがある、んでそこにセッションとかプロファイルが残る、次にアクセスするときは同じサーバーにアクセスさせないといけない
    • つらい
  • ステートレスアーキテクチャ
    • 共有データストアにセッションとかのるから気にしなくて良い
    • scalable

データセンター

  • 概要
    • 複数のリージョンにまたがってサーバーを用意することで冗長性を担保したり、ユーザーの位置によって振り分けたりするやつ
  • 技術的な壁
    • トラフィックのリダイレクト
      • ジオDNSなどで適切なデータセンターへの誘導を行う
    • データの同期
      • 地域が異なればキャッシュやローカルデータベースも異なるかもしれない。障害で他のデータセンターを利用させるとき、普段使っているそれらがつかえなくなるかも。
      • 常にコピーしておくとか

メッセージキュー

  • 概要
    • 「メモリに格納された耐久性のある構成要素であり、非同期通信をサポート」する
  • 詳細
    • パブリッシャーがキューにメッセージを入れといて、サブスクライバーがそれを読みに行く
    • パブリッシャーとかサブスクライバーが落ちててももう片方の挙動に影響しない
  • 感想
    • これパブリッシャーとかサブスクライバーと比較して、キューの信頼性が格段に優れているってことだよね??
      • どのようにそれを保証するんだろ?
      • 0.9, 0.9, 0.9の信頼性なら、キューが死なない限り問題ない(?)から0.9で、けど直に繋ぐとどっちかダメならダメになるから0.81になるのか。たしかに同程度の信頼性でもキュー挟んだ方が信頼性高いな

ログ取得、定量化、自動化

  • ログ取得
    • エラーログの監視。複数サーバーのログを一元化して取得するみたいなのも可能
  • 定量化
    • ヘルスチェック
      • ホストのやつ、データベースまわり
    • マーケティング指標の取得
  • 自動化
    • CI/CD

データベースのスケーリング

  • 垂直スケーリング
    • 限界ある、単一障害点になる、金が高い
  • 水平スケーリング(シャーディング)
    • レプリケーションとは別の手法
      • データ量があまりに大きくて単一のデータベースサーバーで扱えなくなった時にやるてことかな?
    • データベースを同じスキーマのまま複数に分散させる
    • デメリット
      • データが増えたときに再シャーディングが必要になる
      • 結合と非正規化
      • セレブ問題(過負荷をもたらすデータが集中する問題)

100万ユーザーへの対応

  • だいたい以下のような要素が必要
    • Web層はステートレスに保つ
    • 各階層で冗長性を確保する
    • データのキャッシュ化
    • データセンターを複数にする
    • 静的アセットをCDNでホスティングする
    • シャーディングによるデータ層の拡張
    • 各サービスに階層を分割する
    • システム監視と自動化ツールの使用

感想

  • こういうの、自分は全く知らない魔法みたいなことをやってるんだと思ってたけど、そうでもなかった
    • 考えたら分かることをやってる
  • シャーディングまわりはまだ課題が多い
    • ここは面白そう

第2章 おおまかな見積もり

  • 概要
    • システム容量や性能要件の見積もり

2のべき乗(p44)

  • 概要
    • 2の10乗が約1000であり1KB
    • 以降1MB, 1GB, 1TB, 1PBと続く
  • 感想
    • ここで書かれてるデータ容量ってなに???

プログラマが知っておくべきレイテンシの数値(p45)

  • ざっくりとしたアクセス時間の傾向
    • メモリは速い、ディスクは遅い
    • ディスクのシークは避ける
    • 単純な圧縮アルゴリズムははやい
    • データ転送まえに圧縮すべき
    • 遠いデータセンターに送ると時間がかかる

可用性の数値

  • 概要
    • SLAとかで結ばれる可用性99.9%とかって具体的にはこんな時間よというやつ
  • 99.9%
    • 一日に1.4分

演習: Twitterのケース

  • 問題
    • メディア用ストレージの容量を計算せよ
  • 考え方
    • 以下の要素で計算できる
    • 一日に投稿されるメディアの容量
      • 一日のツイート数
      • メディア付きツイートの割合
      • メディアの平均容量
    • 保存期間
  • 計算
    • 要素
      • 一日に3億ツイート
      • メディア付きは10%
      • ひとつあたり1MB
      • 保存期間は5年
    • 計算3億×10%×1MB×365×5
      • 55PB

注意点

  • 概算で出す
    • こまけーこまけー数字はどうでもよくて、考え方の方がたいせつ
    • たぶんひとつひとつの数字が正しいかどうかも問われてない
  • 単位を示す
  • よく聞かれるやつ
    • QPS, ピークQPS, ストレージ、キャッシュ、サーバー数

第3章 システム設計の面接試験のフレームワーク

  • 設計試験の主眼はなにか?
    • 問題解決の様子を見たいだけ

試験の4ステップ

  • 問題の把握、設計範囲の合意
    • ゆっくり要件を合意しようね
  • 高度な設計を提案して賛同を得る
    • ざっくり書いて、面接官に意見を求めたりする
    • 考えをホワイトボードに書いたりして共有する
  • 設計の深掘り
    • ざっくりとした設計に対してフィードバックをもらうことで、面接官がどこにフォーカスしたいかが分かる
  • 面接官からの質問とまとめ
    • 面接官からなんらかのツッコミがはいるので、それに答える
    • 相手に感想を求めるのも良い
    • 改良できる点があれば言及してしてもよい。運用とかもよい
  • 感想
    • せやなあと思った、そらなあと

第4章 レートリミッターの設計

  • 概要
    • 一定期間に受け付けられるリクエストの回数を制限するやつ
  • レートリミッターのメリット
    • DoS攻撃によるリソース枯渇を防ぐ
    • コスト削減
      • 有料の外部API使ってたりするとなおさら
    • サーバー負荷軽減

問題を把握し、設計範囲を明確にする

  • 質問できること
    • 制限ルールはどんなもの? 可変?
    • 単一のアプリ向けに作る? それとも複数のアプリケーションで共有可能?
    • システム規模は?
    • toB, C? アクセスの規模は上がある?
    • 制限があったときにユーザーに通知したい?
  • 追加できる要件!!!
    • どれくらいの工数で作って欲しい?
    • 言語に制限あるか? 技術スタックは?
    • そもそも外部サービスじゃダメ?
    • すでに使ってないの? それに組み込めない?
  • 感想
    • これ、どんな種類のシステムがこの世に存在するのか調べた上で、そのバリエーションを網羅すれば要件定義ってある程度できるな。。
    • 辞書が必要なんだなつまりは
      • それってSESで案件の詳細みれたら分かるのでは?
      • けど要件定義終わってないと無理か
      • こういうメディア作りたいんだけど、どれくらい金かかるかな
  • メディア作る
    • 50人から3つずつのサービスについてシステム構成を教えてもらう
    • ひとり3000円の飲み会として
      • 45万円か〜てか3000円でそんな喋ってくれるか? みたいなのあるよなあ
    • 面接官の練習台やりますとかでやった方がいいな

高度な設計を提案し賛同を得る

  • とれる選択肢
    • クライアント側での実装
      • セキュリティ的にきつい
    • サーバー側での実装
    • ミドルウェアとして実装
    • クラウドマイクロサービスの利用
  • よくあるアルゴリズム
    • トークンバケット
      • トークンがコンテナに入ってて、一定期間で補充される。アクセスがあったとき、リクエストはトークンをひとつ取り出してAPIの方に行く。レートを超えるとトークンがなくてリクエストは破棄される。
      • 実装やメモリ効率はよいが、トークン上限と補充率を適切に決めるのが大変
    • リーキーバケット
      • 一定期間ごとに処理されるキューにアクセスを突っ込んでいく。キューが満杯のときは処理されない。
      • 処理が一定速度になる以外はトークンバケットとおなじ
    • 固定ウインドウカウンタ
      • ぱっと見た感じトークンバケットと同じっぽい
      • 一定の時間のスライスごとに落とせるリクエストの数が決まっていて、時間が過ぎたら新しいのが通れるってだけ(レーティングってそういうことですが)
    • スライディングウインドウログ
    • スライディングウインドウカウンタ
  • 感想
    • トークンバケットがトラフィックのバースト対策になる理由がわからん
      • リーキーバケットではデメリットにされてるのもわからん

設計の深掘り

  • さらに深掘りできる点
    • レーティングルールをどうするか
    • レート制限に関するレスポンス
    • 詳細設計をまとめる
      • 構成をまとめる。クライアントからミドルウェアにいって制限ルールを読み込んでキャッシュにいれとき、制限に使うバケットとかはRedisで管理、漏れたリクエストは破棄するかキューに積むか
    • 分散環境のレートリミッター
      • レースコンディション
      • 同期の問題
    • モニタリング

まとめをする

  • する

第5章 コンシステントハッシュの設計

概要

  • コンシステントハッシュとは
    • サーバー間で効率よく均等にリクエストやデータを分散させるための仕組み
    • ここになんかこうハッシュ関数を使ってサーバを割り当てる仕組みがあるらしくて、しかしその値は振り直されると全部やり直しになるのでそこが改善されたコンシステントハッシュが必要
  • 従来の基本的なアルゴリズム
    • ハッシュマップに均等にマッピングすることでいい感じに分散できる
    • あるキーが自分の配置されているサーバを知るには、サーバの位置からみて最初のハッシュ値を知らねばならぬ
  • 問題点
    • マッピングがうまくばらけない
    • うまくばらけないので、キーも不均一に分散する
  • 仮想ノード
    • サーバひとつにつき10とかをマッピングすれば平均がとれて分散する
  • 再配分問題
    • サーバがなくなったり追加されても、本来どこに配分されるべきかが分かるため、すべて振り直しにはならない

感想