足がかりとしては最適、だが信頼しすぎることは危険-『大規模サービス技術入門』

webサービスを提供するってことは、どんなことに頭を悩ませて、どのように解決していくんだろう?

そんな疑問を解消するのには、もってこいの一冊。

なんとなく、大規模データを取り扱う時には苦労があるんだろうなぁ...程度にしか捉えていなかったwebサービスの裏側を垣間見ることができたのは収穫だった。

...しかし、ハテナのインターンシップはここまで丁寧に現場の話を聞けるのか...

所々で読み取れるインターンシップ生の技術レベルの高さに羨ましさを覚える反面、ここまでのサポートができるからこそ社内に技術が根付き、そこを基点にしてまた人が集まってくる、そういった良い循環が生まれているに違い無い。

さて、なにはともあれ目次を載せておこう。

第1回 大規模Webサービスの開発オリエンテーション―全体像を把握する

Lesson 0 本書の源 ―本書で説明すること,しないこと

大規模サービスの開発に携わる ―大学生向けのはてなインターンシップ
本書で説明すること
本書で説明しないこと
これから大規模サービスと向き合うみなさんへ
Lesson 1 大規模なサービスと小規模なサービス

はてなのサービス規模
はてなは大規模,GoogleやFacebookは超大規模
小規模サービスと大規模サービスの違い
スケーラビリティ確保,負荷分散の必要
冗長性の確保
省力運用の必要
開発人数,開発方法の変化
大規模データ量への対処
Lesson 2 成長し続けるサービスと,大規模化の壁

Webサービスならではの難しさ
はてなが成長するまで
試行錯誤のシステム規模拡張
データセンターへの移設,システムの刷新
システムの成長戦略 ―ミニマムスタート,変化を見込んだ管理と設計
Lesson 3 サービス開発の現場

はてなの技術チーム体制
はてなでのコミュニケーションの仕方
サービス開発の実際
開発に使うツール
プログラミング言語 ―Perl,C/C++,JavaScriptなど
おもなミドルウェア ―ミドルウェア/フレームワークも統一
Webアプリケーションフレームワーク ―自社開発のRidge
手元のマシンのOSやエディタ ―基本的に自由
バージョン管理はgit,BTSは独自開発の「あしか」
開発ツールに関して
まとめ
第2回 大規模データ処理入門 ―メモリとディスク,Webアプリケーションと負荷

Lesson 4 はてなブックマークのデータ規模 ―データが大きいと処理に時間がかかる

はてなブックマークを例に見る大規模データ
はてなブックマークのデータ規模
大規模データへのクエリ ―大規模データを扱う感覚
Column 日々起こる未知の問題 ―試行錯誤しながら,ノウハウを蓄積する
Lesson 5 大規模データ処理の難所 ―メモリとディスク

大規模データは何が難しいのか ―メモリ内で計算できない
メモリとディスクの速度差 ―メモリは105〜106倍以上高速
ディスクはなぜ遅いのか ―メモリとディスク
探索速度に影響を与えるさまざまな要因
OSレベルの工夫
転送速度,バスの速度差
Column Linux単一ホストの負荷 〜『サーバ/インフラを支える技術』ダイジェスト(OSレベルの基礎知識:その1)〜
Lesson 6 スケーリングの要所

スケーリング,スケーラビリティ
スケーリングの要所 ―CPU負荷とI/O負荷
Webアプリケーションと負荷の関係
DBのスケーラビリティ確保は難しい
Column 二種類の負荷とWebアプリケーション〜『サーバ/インフラを支える技術』ダイジェスト(OSレベルの基礎知識:その2)〜
Lesson 7 大規模データを扱うための基礎知識

プログラマのための大規模データの基礎
大規模データを扱う三つの勘所 ―プログラムを作るうえでのコツ
大規模データを扱う前に。三大前提知識 ―プログラム開発のさらに下の基礎
Column ロードアベレージの次は,CPU使用率とI/O待ち率〜『サーバ/インフラを支える技術』ダイジェスト(OSレベルの基礎知識:その3)〜
第3回 OSのキャッシュと分散 ―大きなデータを効率良く扱うしくみ

Lesson 8 OSのキャッシュ機構

OSのキャッシュ機構を知ってアプリケーションを書く ―ページキャッシュ
Linux(x86)のページング機構を例に
仮想メモリ機構
Linuxのページキャッシュのしくみ
ページキャッシュの身近な効果
VFS
Linuxはページ単位でディスクをキャッシュ
LRU
(補足)どのようにキャッシュされるか ―iノードとオフセット
メモリが空いていればキャッシュ ―sarで確認してみる
メモリを増やすことでI/O負荷軽減
ページキャッシュは透過的に作用する
Column sarコマンドでOSが報告する各種指標を参照する〜『サーバ/インフラを支える技術』ダイジェスト(OSレベルの基礎知識:その4)〜
Lesson 9 I/O負荷の軽減策

キャッシュを前提にしたI/O軽減策
複数サーバにスケールさせる ―キャッシュしきれない規模になったら
単に台数を増やしてもスケーラビリティの確保はできない
Column I/O負荷軽減とページキャッシュ〜『サーバ/インフラを支える技術』ダイジェスト(OSレベルの基礎知識:最終回)〜
Lesson 10 局所性を活かす分散

局所性を考慮した分散とは?
パーティショニング ―局所性を考慮した分散①
リクエストパターンで「島」に分割 ―局所性を考慮した分散②
ページキャッシュを考慮した運用の基本ルール
Column 負荷分散とOSの動作原理 ―長く役立つ基礎知識
第4回 DBのスケールアウト戦略 ―分散を考慮したMySQLの運用

Lesson 11 インデックスを正しく運用する ―分散を考慮したMySQL運用の大前提

分散を考慮したMySQL運用,3つのポイント
①OSのキャッシュを活かす
[補足]正規化
インデックス重要 ―B木
二分木とB木を比べてみる
MySQLでインデックスを作る
インデックスの効果
インデックスの効果の例
[補足]インデックスの作用 ―MySQLの癖
インデックスが効くかどうかの確認法 ―explainコマンド
explainコマンドで速度に気を付ける
Column インデックスの付け忘れ ―見つけやすいしくみでカバー
Lesson 12 MySQLの分散 ―スケーリング前提のシステム設計

MySQLのレプリケーション機能
マスタ/スレーブの特徴 ―参照系はスケールする,更新系はスケールしない
更新/書き込みをスケールさせたい ―テーブル分割,key-valueストア
Lesson 13 MySQLのスケールアウトとパーティショニング

MySQLのスケールアウト戦略
パーティショニング(テーブル分割)にまつわる補足
パーティショニングを前提にした設計
JOINを排除 ―where ... in ...を利用
DBIx::MoCo
パーティショニングのトレードオフ
運用が複雑になる
故障率が上がる
冗長化に必要なサーバ台数は何台?
アプリケーションの用途とサーバ台数
サーバ台数と故障率
第2回〜第4回の小まとめ
第5回 大規模データ処理[実践]入門 ―アプリケーション開発の勘所

Lesson 14 用途特化型インデクシング ―大規模データを捌く

インデックスとシステム構成 ―RDBMSの限界が見えたとき
RPC,Web API
用途特化型のインデクシング ―チューニングしたデータ構造を使う
[例]はてなキーワードによるリンク
[例]はてなブックマークのテキスト分類器
全文検索エンジン
Lesson 15 理論と実践の両側から取り組む

求められる技術的な要件を見極める
大規模なWebアプリケーションにおける理論と実践
計算機の問題として,道筋をどう発見するか
第2回〜第5回の小まとめ
第6回 [課題]圧縮プログラミング ―データサイズ,I/O高速化との関係を意識する

Lesson 16 [課題]整数データをコンパクトに持つ

整数データをコンパクトに持つ
出題意図 ―この課題を解けると何がいいの?
課題で扱うファイルの中身
Lesson 17 VB Codeと速度感覚

VB Code ―整数データをコンパクトに保持しよう
VB Codeの擬似コード
アルゴリズム実装の練習
ソート済み整数を「ギャップ」で持つ
(補足①)圧縮の基礎
(補足②)対象が整数の場合 ―背景にある理論
Lesson 18 課題の詳細と回答例

課題の詳細
評価基準
(参考①)pack( )関数 ―Perl内部のデータ構造をバイナリで吐き出す
今回の課題におけるpackの使いどころ
(参考②)バイナリのread/write
(参考③)プロファイリング
回答例と考え方
プログラム本体
第7回 アルゴリズムの実用化 ―身近な例で見る理論・研究の実践投入

Lesson 19 アルゴリズムと評価

データの規模と計算量の違い
第7回,二つの目的
アルゴリズムとは?
狭義のアルゴリズム,広義のアルゴリズム
アルゴリズムを学ぶ意義 ―計算機の資源は有限,エンジニアの共通言語
アルゴリズムの評価 ―オーダー表記
各種アルゴリズムのオーダー表記
ティッシュを何回折りたためるか? ―O(log n)とO(n)の違い
アルゴリズムにおける指数的,対数的の感覚
アルゴリズムとデータ構造 ―切っても切れない関係!?
計算量と定数項 ―やはり計測が重要
実装にあたって気を付けたい最適化の話
アルゴリズム活用の実際のところ ―ナイーブがベターなことも?
はてなブックマークFirefox拡張の検索機能における試行錯誤
ここから,学んだこと
サードパーティの実装を上手に活用しよう ―CPANなど
実例を見て,実感を深める
Column データ圧縮と速度 ―全体のスループットを上げるという考え方
Lesson 20 はてなダイアリーのキーワードリンク

キーワードリンクとは?
当初の実装
問題発生! ―キーワード辞書が大規模化してくる
パターンマッチによるキーワードリンクの問題点
正規表現➡Trie ―マッチングの実装切り替え
Trie入門
Trie構造とパターンマッチ
AC法 ―Trieによるマッチングをさらに高速化
Regex::Listへの置き換え
キーワードリンク実装,変遷と考察
Lesson 21 はてなブックマークの記事カテゴライズ

記事カテゴライズとは?
ベイジアンフィルタによるカテゴリ判定
機械学習と大規模データ
はてなブックマークの関連エントリー
大規模データとWebサービス ―The Google Way of Science
ベイジアンフィルタのしくみ
ナイーブベイズにおけるカテゴリの推定
楽々カテゴリ推定の実現
アルゴリズムが実用化されるまで ―はてなブックマークでの実例
実務面で考慮すべき点はそれなりに多い
守りの姿勢,攻めの姿勢 ―記事カテゴライズ実装からの考察
既存の手法を引き出しに入れておく
Column スペルミス修正機能の作り方 ―はてなブックマークの検索機能
第8回 [課題]はてなキーワードリンクの実装 ―応用への道筋を知る

Lesson 22 [課題]はてなキーワードリンクを作る

AC法を使って,はてなキーワードリンクを作る
サンプルプログラム
AC法の実装の仕方
実際の課題
出題意図
テストを書こう
Column アルゴリズムコンテスト ―Sphere Online Judge,TopCorderなど
Lesson 23 回答例と考え方

回答例
第9回 全文検索技術に挑戦 ―大規模データ処理のノウハウ満載

Lesson 24 全文検索技術の応用範囲

はてなのデータで検索エンジンを作る
はてなダイアリーの全文検索 ―検索サービス以外に検索システム
以前はRDBで処理していた
はてなブックマークの全文検索 ―細かな要求を満たすシステム
Lesson 25 検索システムのアーキテクチャ

検索システムができるまで
今回の解説対象
検索エンジンいろいろ
全文検索の種類
grep型
Suffix型
転置インデックス型
Lesson 26 検索エンジンの内部構造

転置インデックスの構造 ―Dictionary+Postings
Dictionaryの作り方 ―転置インデックスの作り方1
言語の単語をtermにする2つの方法
①辞書とAC法を使う方法
②形態素解析を使う方法(形態素を単語とみなしtermにする)
検索漏れ
n-gramをtermとして扱う
クエリも同じルールで分割する
n-gram分割の問題とフィルタリング
再現率(Recall)と適合率(Precision)
検索システムの評価と再現率/適合率
ここまでの小まとめ
Postingsの作り方 ―転置インデックスの作り方2
今回は出現位置を保持しない,文書IDのみを保持するタイプ
スコアリングについて補足
参考文献
第10回 [課題]全文検索エンジンの作成 ―基本部分,作り込み,速度と精度の追求

Lesson 27 [課題]はてなブックマーク全文検索を作る

全文検索エンジンの開発
課題内容
課題が解けると何がいいの?
サンプルデータの形式とデータサイズ
辞書の構成 ―Dictionary,Postings
インタフェース
基本部分+作り込み
速度と精度で勝負
Lesson 28 回答例と考え方

回答例
indexer.plの実装
searcerh.plの実装
改善できるところは?
Column Twitterのスケールアウト戦略 ―基本戦略とサービスの特徴に合わせた戦略
第11回 大規模データ処理を支えるサーバ/インフラ入門 ―Webサービスのバックエンド

Lesson 29 エンタープライズ vs. Webサービス

エンタープライズ vs. Webサービス ―応用範囲に見る違い
Webサービスの特徴 ―エンタープライズとの比較
Webサービスのインフラ ―重視される3つのポイント
Lesson 30 クラウドvs.自前インフラ

クラウドコンピューティング
クラウドのメリット,デメリット
はてなでのクラウドサービスの使用
自前インフラのメリット
自前インフラと垂直統合モデル
はてなのサービス規模
はてなブックマークのシステム構成図
第12回 スケーラビリティの確保に必要な考え方 ―規模の増大とシステムの拡張

Lesson 31 レイヤとスケーラビリティ

スケーラビリティへの要求 ―サーバ1台で捌けるトラフィックの限界
レイヤごとのスケーラビリティ
Lesson 32 負荷の把握,チューニング

負荷の把握 ―可視化した管理画面
負荷を測るための項目 ―ロードアベレージ,メモリ関連,CPU関連
用途ごとに合わせたチューニング ―ユーザ用のサーバ,ボット用のサーバ
APサーバ/DBサーバのチューニングポリシーと,サーバ台数
サービスの規模とチューニング
スケーラビリティの確保
第13回 冗長性の確保,システムの安定化 ―ほぼ100%の稼動率を実現するしくみ

Lesson 33 冗長性の確保

冗長性の確保 ―APサーバ
冗長性の確保 ―DBサーバ
マルチマスタ
冗長性の確保 ―ストレージサーバ
Lesson 34 システムの安定化

システムを安定させるためのトレードオフ
システムの不安定要因
①機能追加,②メモリリーク
③地雷
④ユーザのアクセスパターン
⑤データ量の増加
⑥外部連携の追加
⑦メモリ ・ HDD障害,❽NIC障害
Lesson 35 システムの安定化対策

実際の安定化対策 ―適切なバッファの維持と,不安定要因の除去
異常動作時の自律制御
第14回 効率向上作戦 ―ハードウェアのリソースの使用率を上げる

Lesson 36 仮想化技術

仮想化技術の導入
仮想化技術の効用
仮想化サーバの構築ポリシー
仮想化サーバ ―Webサーバ
仮想化サーバ ―DBサーバ
仮想化によって得られたメリットの小まとめ
仮想化と運用 ―サーバ管理ツールで仮想化のメリットを運用上活かす
仮想化の注意点
Lesson 37 ハードウェアと効率向上 ―低コストを実現する要素技術

プロセッサの性能向上
メモリ,HDDのコスト低下
メモリ ・ HDDの価格の推移
安価なハードの有効利用 ―仮想化を前提としたハードウェアの使用
SSD
Column SSDの寿命 ―消耗度合いの指標に注目!
第15回 Webサービスとネットワーク ―ネットワークで見えてくるサービスの成長

Lesson 38 ネットワークの分岐点

サービスの成長とネットワークの分岐点
1Gbpsの限界 ―PCルータの限界
500ホストの限界 ―1サブネット,ARPテーブル周りでの限界
ネットワーク構造の階層化
グローバル化
CDNの選択肢
Amazon Cloudfront
Lesson 39 さらなる上限へ

10Gbps超えの世界
はてなのインフラ ―第11回〜第15回のまとめ
特別編 いまどきのWebサービス構築に求められる実践技術 ―大規模サービスに対応するために

Special Lesson 1 ジョブキューシステム ―TheSchwartz、 Gearman

Webサービスとリクエスト
ジョブキューシステム入門
はてなでのジョブキューシステム
TheSchwartz
Gearman
WorkerManagerによるワーカーの管理
ログからの分析
Special Lesson 2 ストレージの選択 ―RDBMSかkey-valueストアか

増大するデータをどう保存するか
Webアプリケーションとストレージ
適切なストレージ選択の難しさ
ストレージ選択の前提となる条件
ストレージの種類
RDBMS
MySQL
MyISAM
InnoDB
Mariaなど
MyISAM vs. InnoDB
分散key-valueストア
memcached
TokyoTyrant
分散ファイルシステム
MogileFS
その他のストレージ
NFS系分散ファイルシステム
WebDAVサーバ
DRBD
HDFS
ストレージの選択戦略
Special Lesson 3 キャッシュシステム ―Squid,Varnish

Webアプリケーションの負荷とプロキシ/キャッシュシステム
リバースプロキシキャッシュサーバ
Squid ―基本的な構成
複数台で分散する
二段構成のキャッシュサーバ ―CARPでスケールさせる
COSSサイズの決定方法
投入時の注意
Varnish
Special Lesson 4 計算クラスタ ―Hadoop

大量ログデータの並列処理
MapReduceの計算モデル
Hadoop

大規模サービス入門とうたっているだけあって取り扱っている内容は広く浅くだ。
もともとインターンシップに向けて書かれているだけあって、業界のガイドブックとしての役割は十分に果たせていると思う。

隣の庭の具合をチョロっと覗いてみたいというニーズには間違いなく最高のガイドブックとして機能するだろう。

難点と言うか、あえて難癖をつけるとしたら、あまりにも"現在"を切り取りすぎていて、旬が限定されることだろう。

今、この時ほど本書の価値が高い瞬間は無い。

さて、本書から学んだ点は2点。

1. 基礎研究を繰り返し、手持ちの武器を増やし続けることの重要さ
2. 社内の技術レベルの維持/向上の手法

1点目の観点からみると、読みどころは「第7回 アルゴリズムの実用化」の部分。
単独でアルゴリズムの基礎論として読み進めても十分に読み応えがあるが、それだけで終わらせてしまうのはもったいない。
基礎概念があって、必要なアルゴリズムを選択・実装していく。
いや、時には実装の必要はないのかもしれない、他に最適な実装を借りてくることができれば...
だが、いつか利用する時の為の知識の仕入れ期間は他人から借りてくることはできない。
基礎研究を繰り返し、自分の力に変えることができなければ、最適な実装も手を抜いた実装も出来ない。
だからこそ基礎研究は大切なのだ。

職業プログラマはプログラムが好きだから続けられるんじゃなく好きでなければ続けられない、そんなことを再認識させられた。

さしあたって、ベイズ推論についてはたまたま他で資料を手にしていたので早速実装してみよう。

...しかし、面白くなってしまうと、形態素解析とかもやりたくなってくるんだろうなぁ...

2点目の観点から本書を眺めた時、問題提起から始まり基礎論そして発展技術と紹介して実習に進む構成がうまいと感じた。
なんとなく講義を聞いていたとしても、敗者や落ちこぼれが出にくい構成になっていると思う。

さすがに定期的に社内勉強会としてこのレベルのものを続けることは難しいとは思うが、一つの形として非常に参考になる。

...反面、至れり尽くせりがすぎやしないのか?とも感じてしまう。

水先案内人が手をひいて導いてくれている間は良い、さて「ここから先は一人で歩いてね」となった時、優秀だった生徒はどうなるんだろう?

いつかは自分がスライドを用意し、ホワイトボードの前で"今"の技術を説明できるようになっていなければならない。

その覚悟があって講義を聞いているのか、単にお客さんで終わってしまうのか...インターンシップ生はそこを見られていたのではないのか?