081108huge_data.ppt
TRANSCRIPT
はてな流大規模データ処理
アジェンダ
大規模なデータ OS のキャッシュ MySQL の運用 大規模データアプリケーションの開発
大規模なデータ
大規模データ
はてなブックマーク
mysql> select count(*) from relword;+----------+| count(*) |+----------+| 51780147 |+----------+1 row in set (0.00 sec)
はてなブックマークのデータ規模
レコ―ド数 1,073 万エントリー 3,134 万ブックマーク 4,743 万タグ
データサイズ エントリー 2.5GB ブックマーク 4GB タグ 3.4GB HTML 100GB 超
大規模データへのクエリ
mysql> select url from entry use index(hoge) where eid = 9615899;
... 200 秒待っても結果が返って来ない
大規模データの難しい所
メモリ内で計算できない
メモリとディスクの速度差
% sudo /sbin/hdparm -tT /dev/sda
/dev/sda: Timing cached reads: 15012 MB in 1.99 seconds = 7525.03 MB/sec Timing buffered disk reads: 176 MB in 3.02 seconds = 58.37 MB/sec
メモリはディスクの 100 倍以上高速 メモリ 7 .5 GB/sec ディスク 58MB/sec
スケーリングの要所
CPU 負荷のスケーリングは簡単 同じ構成のサーバーを増やす、 LB で分散 Web, AP サ―バ , クローラー
I/O 負荷のスケーリングは難しい 大規模データ データベース
大規模データを扱うコツ
いかにしてメモリで済ませるか 局所性を活かした分散
データ量の増加に強いアルゴリズム、データ構造
例 : 線形探索 → 二分探索 O (n) → O (log n)
圧縮、情報検索技術
大規模データを前に知っておくべき事
OS のキャッシュ層 分散を考慮した RDBMS の運用 アルゴリズムとデータ構造
OS のキャッシュ
メモリとディスク
メモリとディスクの速度は 150 倍 メモリを使ってディスクアクセスを減ら
す
OS のキャッシュ
Linux のページキャッシュの特性
Linux (x86) のページング機構
仮想メモリ機構の基盤 論理的なリニアアドレスを物理的な物理
アドレスへ変換
リニアアドレス
ページング機構(MMU)
物理アドレス
0xbffff444
0x00002123
Linux (x86) のページ
フラットメモリモデル ページ = 仮想メモリの最小単位
4kb の構造体 ページキャッシュ = カーネルバッファ
に残った page 構造体
Linux のページキャッシュとディスク
ディスクの内容をメモリに読み込む ページが作成される
作成したページは破棄せずに残す = ページキャッシュ
例外を除きすべての I/O に透過的に作用する
ディスクのキャッシュを担う箇所 ... VFS
デバイスドライバ
VFS
ext2 ext3 ext4 xfs tmpfs
vfs
VFS の役割
(1) ファイルシステム実装の抽象化 (2) パフォーマンス
ページキャッシュ
VFS データ構造関係図
superblock
inodedentry file
address_space
page page page
inode
inode
1
*
1
*
1
1
11 1 1
(2) offset
(1) inode番号
Linux はページ単位でディスクをキャッシュ
ファイルオフセット + i ノード番号がインデックス
ファイルの一部をキャッシュできる
address_space → page(s) は Radix Tree 検索コストはファイルの大きさにほとんど依
存しない
キャッシュの単位
ページ = 仮想メモリの最小単位 ページキャッシュ ≠ ファイルキャッシュ ページキャッシュ = カーネルバッファに
残った page 構造体
メモリが空いていればキャッシュ
制限なし sar –r で確認
% sar -r 1 10000
Linux 2.6.11-co-0.6.4 (colinux) 05/28/07
19:50:32 kbmemfree kbmemused %memused kbbuffers kbcached kbswpfree kbswpused %swpused kbswpcad
19:50:33 5800 1005888 99.43 28244 694088 262132 4 0.00 0
19:50:34 5800 1005888 99.43 28244 694088 262132 4 0.00 0
19:50:35 5800 1005888 99.43 28244 694088 262132 4 0.00 0
19:50:36 5800 1005888 99.43 28244 694088 262132 4 0.00 0
メモリを増やすことで I/O 負荷軽減
14:10:01 CPU %user %nice %system %iowait %idle
14:20:01 all 8.58 0.00 5.84 16.58 69.00
14:30:01 all 7.41 0.00 5.14 17.81 69.63
14:40:01 all 7.74 0.00 4.97 18.56 68.73
14:50:01 all 7.02 0.00 5.01 16.24 71.72
14:10:01 CPU %user %nice %system %iowait %idle
14:10:01 all 18.16 0.00 11.56 0.80 69.49
14:20:01 all 12.48 0.00 9.47 0.88 77.17
14:30:01 all 14.20 0.00 10.17 0.91 74.72
14:40:01 all 13.25 0.00 9.74 0.75 76.25
メモリ 4GB
メモリ 8GB
透過的に作用する
18:20:01 kbmemfree kbmemused %memused kbbuffers kbcached kbswpfree kbswpused %swpused kbswpcad
18:30:01 3566992 157272 4.22 11224 50136 2048276 0 0.00 0
18:40:01 3546264 178000 4.78 12752 66548 2048276 0 0.00 0
18:50:01 112628 3611636 96.98 4312 3499144 2048232 44 0.00 44
OS 起動直後に数 GB のファイルを read した結果
キャッシュを前提にした I/O 軽減策 データ規模 < 物理メモリなら全てキャ
ッシュできる
経済的コストとのバランスを考慮 現状のコモディティ : 8GB ~ 16GB
キャッシュ仕切れない規模になったら
複数サーバーにスケールさせる ただし単純に増やさない
CPU 負荷分散では単純に増やす I/O 分散では局所性を考慮する
自前でインデックスを作る
単純に台数を増やす場合
キャッシュできない割合は相変わらずそのまま
すぐに再度ボトルネックに
コピー
局所性を考慮した分散
アクセスパターンを考慮した分散 キャッシュできない箇所がなくなる
メモリはディスクの 150 倍
アクセスパターン A アクセスパターン B
具体的には
RDBMS のテーブル単位での分割 パーティショニング
検索のインデクスを辞書の途中で分割する A ~ E まではサーバ A F ~ I まではサーバ B ...
用途ごとにシステムを「島」に分ける
proxy
AP
bot / feed
通常のリクエスト
DB
画像 API etc.
proxy
リクエストパターンで「島」に分割
ページキャッシュを考慮した運用
OS 起動後すぐにサーバを投入しない 性能評価はキャッシュが最適化された時
に 分散は局所性を考慮して データ規模に合わせて搭載メモリを調整
する メモリ増設で対応しきれないなら分散
分散を考慮した MySQL の運用
MySQL 運用のポイント
OS のキャッシュを活かす インデックスを適切に設定する スケーリングを前提とした設計
OS のキャッシュを活かす
全データサイズに気を配る データ量 < 物理メモリ を維持 メモリが足りない場合は増設 etc.
インデックス重要
インデックス = 索引 B 木 O(n) → O(log n)
インデックスの効果
例 : 4,000 万件のタグデーブルからの検索
インデックスなし = 線形探索 → O(n) → 最大 4,000 万回の探索
インデックスあり = B 木で二分探索 → O(log n) → log24000 万 = 最大 25.25
回
インデックスの効果の例
mysql> select url from entry where eid = 9615899;+------------------------------------------------------------------------------+| url |+------------------------------------------------------------------------------+| http://builder.japan.zdnet.com/member/u87200/blog/2008/08/10/entry_27012867/ |+------------------------------------------------------------------------------+1 row in set (0.00 sec)
mysql> select url from entry use index(hoge) where eid = 9615899;
... 200 秒待っても結果が返って来ない
インデックスの作用
where 、 order by 、 group by の条件 プライマリキー、 UNIQUE 制約 明示的に追加したインデックス
罠 複数のカラムに同時にインデックスを効かせたい場
合は複合インデックス select * from entry where url like
'http://d.hatena.nejp/%' order by timestamp
インデックスが効くかどうかの確認
explain
mysql> explain select url from entry where eid = 9615899;+-------+------+---------------+------+---------+-------+------+-------------+| table | type | possible_keys | key | key_len | ref | rows | Extra |+-------+------+---------------+------+---------+-------+------+-------------+| entry | ref | eid | eid | 4 | const | 1 | Using where |+-------+------+---------------+------+---------+-------+------+-------------+1 row in set (0.04 sec)
mysql> explain select url from entry use index(cname) where eid = 9615899;+-------+------+---------------+------+---------+------+---------+-------------+| table | type | possible_keys | key | key_len | ref | rows | Extra |+-------+------+---------------+------+---------+------+---------+-------------+| entry | ALL | NULL | NULL | NULL | NULL | 9620451 | Using where |+-------+------+---------------+------+---------+------+---------+-------------+1 row in set (0.01 sec)
より詳しくは
MySQL の分散
マスタ・スレーブ 参照系はスレーブへ、更新はマスタへ
OR マッパで制御する
アプリケーションサーバー
アプリケーションサーバー
アプリケーションサーバー
アプリケーションサーバー
ロードバランサ
DBスレーブ DBスレーブDBスレーブ
DBマスタ
マスタ・スレーブの特徴
参照系クエリはスケール サーバーを増やすだけで良い ただし、台数を稼ぐことよりもメモリにフィットさ
せることが重要
マスタはスケールしない 更新系クエリが増えると厳しい ただし、 Web アプリは多くの場合 90 %以上が参
照クエリ マスタ負荷はテーブル分割で凌ぐのが現状のセオリ
ー
MySQL のスケールアウト戦略
データがメモリに載るサイズ ? YES → メモリに載せる NO
メモリ増設 メモリ増設が不可能ならパーティショニング
パーティショニング ( テーブル分割 )
テーブル A とテーブル B を別のサーバーに置いて分散する方法
A B A B
パーティショニング
テーブル単位での分割 特定のアルゴリズムでの分割
例 1. 頭文字 a-d が A 、頭文字 e-h が B ... 例 2. ハッシュ関数
パーティショニングはなぜ効果的か
局所性
パーティショニングを前提にした設計
JOIN を使わない RDBMS 屋には叱られるがしょうがない
INNER JOIN している SQL
entry has many bookmarks
mysql> select url from entry INNER JOIN bookmark on entry.eid = bookmark.eid -> where bookmark.uid = 169848 limit 5;+-------------------------------------------------------------------+| url |+-------------------------------------------------------------------+| http://blog.bulknews.net/mt/archives/001537.html || http://www.wrightthisway.com/Articles/000154.html || http://internet.watch.impress.co.jp/cda/news/2005/02/10/6438.html || http://headlines.yahoo.co.jp/hl?a=20050210-00000136-kyodo-bus_all || http://headlines.yahoo.co.jp/hl?a=20050210-00000015-maip-soci |+-------------------------------------------------------------------+
JOIN を排除 where ... in ... を利用mysql> select eid from bookmark where uid = 169848 limit 5;+-----+| eid |+-----+| 0 || 4 || 5 || 6 || 7 |+-----+5 rows in set (0.01 sec)
mysql> select url from entry where eid in (0, 4, 5, 6, 7);+-------------------------------------------------------------------+| url |+-------------------------------------------------------------------+| http://blog.bulknews.net/mt/archives/001537.html || http://www.wrightthisway.com/Articles/000154.html || http://internet.watch.impress.co.jp/cda/news/2005/02/10/6438.html || http://headlines.yahoo.co.jp/hl?a=20050210-00000136-kyodo-bus_all |+-------------------------------------------------------------------+4 rows in set (0.12 sec)
DBIx::MoCo
$entry->bookmarks(0, 5) JOIN は使わない where ... in ... を使ってプライマリキ
ーで結合
パーティショニングのトレードオフ
良い点 負荷が下がる 局所性が増してキャッシュ効果が高くなる
悪い点 運用が複雑になる、故障確率が上がる
運用が複雑になるとその分経済的コストがかかる。メモリは今時 2GB で 5,000 円。
パーティショニングはあくまで切り札。
大規模データアプリケーションの開発
Q. 敢えて大量データにアクセスしたい
全文検索 はてなのキーワードリンク 類似文書探索 データマイニング ...
A. RDBMS では限界
バッチ処理でデータを抽出 別途インデックスサーバを作り RPC でク
エリする
用途特化型のインデクシング
データを定期的に dump dump したデータからデータ構造を構築
検索用の転置インデックス キーワードリンク用の TRIE ...
構造化データを保持したサーバーを C++ で開発、 RPC でアクセス
Thrift
はてなキーワードによるリンク
ある文書が 20 万強のキーワードのうち何を含むか
昔 ... 巨大な正規表現 現在 ... TRIE で Common Prefix
Search Aho-Corasick Double Array TRIE
はてなブックマークのテキスト分類器
Complement Naive Bayes 文書に含まれる単語の出現確率を保持す
るサーバー
全文検索エンジン
大量のデータから検索したい 「いい感じ」の文書を上位に 高速に検索したい
RDBMS の限界
特定のカラムで並び替えることしか出来ない
横断的な検索には向いてない
RDBMS → 情報検索
RDB のデータをバッチで取得 転置インデクスを作って検索アルゴズム
を使う
テキスト走査と転置インデックス
テキスト走査
O(N) grep
Pros 実装が容易 正規表現
Cons 大量のドキュメントに向かない 「複数のドキュメントから、一番欲しいドキュメン
トを検索する」 (ranked retrieval) に向かない
転置インデックス
Pros 大規模データを高速に検索 Ranked retrieval
Cons 設計 / 実装が大変
転置インデックス
索引語 (term) => docIDs (postings list)
転置インデックスのソート
辞書はアルファベット順 辞書から単語を探しやすいように
文書は ID ( 整数 ) 順 圧縮や探索など様々なアルゴリズムで有利
差分を取って δ 符合で圧縮
転置インデックスに対する検索
辞書から検索 ソート済み → 二分探索可 → O(log n)
ヒットした単語の postings list を取得
docID が検索結果
スコアリング → Cosine Similarity
ベクトル空間モデル
ベクトル空間モデル クエリやドキュメントをベクトル化して無限次元の
ベクトル空間に展開 ベクトル空間内で 「近い」 ベクトルを探す → 類似文書
情報検索技術の基盤 クエリに基づいたドキュメントのスコアリング ドキュメント分類 ドキュメントクラスタリング
ドキュメントのベクトル化
ドキュメントをベクトルとして表現 辞書の単語を成分とする無限次元ベクト
ル
Antony and Cleopatra Julius Caesar The Tempest Hamlet Othello Macbeth
Antony 157 73 0 0 0 0
Brutus 4 157 0 1 0 0
Caesar 232 227 0 2 1 1
Calpurnia 0 10 0 0 0 0
Cleopatra 57 0 0 0 0 0
mercy 2 0 3 5 5 1
worser 2 0 1 1 1 0
d1
ベクトル空間モデルのイメージ
t1
d2
d1
d3
d4
d5
t3
t2
θ
φ
Cosine similarity
二つのベクトルの類似度 = 2 ベクトルが作る cosΘ を求める式に等しい
∵ 相関係数 = cosΘ
Cosine similarity
2 ベクトルの内積が最も大きいもの = 最も相関度が高い
例
3 つの小説の 3 語の tf• "Sense and Sensibility"
• "Pride and Prejudice"
• "Wuthering Heights"
ベクトル長で正規化
SaS ・ PaP = 0.999
SaS ・ WH = 0.888
∴ SaS に近いのは WH より PaP
ベクトル空間モデルの内積計算コスト
M次元の内積計算を N ドキュメント数 M ... 辞書の単語数。万単位 N ... ドキュメント数
計算コストを下げる手法が必要
Cosine Similarity のアルゴリズム 現実的な計算時間で計算するには
行列がスパースであることを利用 転置インデックスを利用する
top K が取得できれば良い 様々な手法で足切り
圧縮全文索引
転置インデックスの弱点 分かち書き方式は検索漏れ N-gram 方式は計算量が増加
部分文字列検索 Suffix Arrays ただし SA は空間コストが高い → Compressed Suffix Arrays (PFI's
Sedue)
大規模なバッチ処理
一台で処理仕切れない 例 : httpd のログ
複数サーバーで並列分散処理 → MapReduce
Hadoop
理論と実践
理論と実践の両側から JOIN を使わない etc ... バッドノウハウ
教科書には載っていない ベクトル計算 etc ... 古典的な理論
多くの問題は古典的な理論に帰着する
" やりたいこと "→ " 計算機の問題 " の道筋をどう発見するかが鍵
「キーワードでリンクしたい」 → TRIE で Common Prefix Search
まとめ
GB 単位のデータ処理 TB 、 PB はまた違った世界
メモリ重要 分散を意識した運用 アルゴリズムとデータ構造
参考文献
Daniel P. Bovet 、 Marco Cesati " 詳解Linux カーネル 第 3版 " オライリー・ジャパン 2007
Jeremy D. Zawodny, Derek J. Balling "実践ハイパフォーマンス MySQL" オライリー・ジャパン , 2004
Christopher D. Manning 、 Prabhakar Raghavan 、 Hinrich Schutz "Introduction to Information Retrieval" Cambridge University Press, 2008
" たつをの ChangeLog" IIR カテゴリ http://chalow.net/clsearch.cgi?cat=IIR