はてなブックマークのシステムについて

59
はははははははははは はははははははは 株株株株株株株 / {Shibuya, Kansai}.pm 株株 株株

Upload: naoya-ito

Post on 24-May-2015

12.862 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: はてなブックマークのシステムについて

はてなブックマークのシステムについて

株式会社はてな / {Shibuya, Kansai}.pm伊藤 直也

Page 2: はてなブックマークのシステムについて

自己紹介

株式会社はてな 執行役員 CTO

Page 3: はてなブックマークのシステムについて

アジェンダ

はてなブックマークのこれまでと現状 各種機能の実現方法 パフォーマンスに関する話

Page 4: はてなブックマークのシステムについて

はてなブックマークのこれまでと現状

Page 5: はてなブックマークのシステムについて

はてなブックマーク

Page 6: はてなブックマークのシステムについて

はてなブックマークのこれまで

2005/2 ベータ版リリース 2005/8 正式版リリース 2008/7 関連エントリー機能

株式会社プリファードインフラストラクチャー (PFI) と共同開発

2008/11 はてなブックマーク 2 システムリニューアル 全文検索 (w/ PFI) 、カテゴライズ etc

2009/4 Firefox 拡張 2009/5 はてなブックマークプラス

有料オプション

Page 7: はてなブックマークのシステムについて

現在の数字

300,000 ユーザー登録 400 万セッション / 月 (Google

Analytics) 1,600 万 URL / 4,700 万 ブックマーク

Page 8: はてなブックマークのシステムについて

データの規模の例

mysql> select count(*) from relword;+-----------+| count(*) |+-----------+| 351277311 |+-----------+1 row in set (0.00 sec)

Page 9: はてなブックマークのシステムについて

データの規模

レコード数 1,600 万 エントリー 4,700 万 ブックマーク 5,000 万 タグ

データサイズ (MySQL MyISAM) エントリー 3GB ブックマーク 5.5GB タグ 4.8GB HTML 200GB 超 (zlib で圧縮済み )

Page 10: はてなブックマークのシステムについて

中規模 ~ 大規模ウェブサービス

サーバ台数 httpd mysqld そのほか

コードの規模 Perl コード 10 万行弱 (WAF 等抜きで 45,000 行 ) .pm ファイル 1,200 個強 (600 個 )

Google, Yahoo!, Amazon が超大規模とすると中規模くらい

レコード数 千万件単位、データ規模は GB 単位

Page 11: はてなブックマークのシステムについて

開発体制

8 名体制 ディレクター ( マネージャ ) 1 名 エンジニア 3 名 + アルバイト 3 名 デザイナー 1 名 + アルバイト 1 名

Page 12: はてなブックマークのシステムについて

システム構成

基本は LAMP ウェブアプリ部分はオーソドックスな構成 Linux (Xen), Apache, MySQL, Perl

用途によってはサブシステムあり 検索用サーバー群 (PFI の Sedue 、自社開発の検索

サーバ ) カテゴライズサーバー スペルミス修正サーバー 非同期タスク用に TheSchwartz 分散ファイルシステムに MogileFS etc.

Page 13: はてなブックマークのシステムについて

プログラミング言語

Perl 5.8 mod_perl WAF ・・・ Ridge ( 自社開発 ) O/R マッパ ・・・ DBIx::MoCo

JavaScript Ten.js ( 自社開発 )

C++ Thrift メモリ要件、速度要求が厳しい箇所

Page 14: はてなブックマークのシステムについて

利用している主なソフトウェア

Perl, JavaScript, C++ LAMP, Xen LVS + keepalived

ロードバランサ Thrift

多言語 RPC フレームワーク (by Facebook) TheSchwartz MogileFS Lux IO

Key Value Store Squid

Page 15: はてなブックマークのシステムについて

各種機能の実現方法

Page 16: はてなブックマークのシステムについて

本文抽出

Page 17: はてなブックマークのシステムについて

HTML::ExtractContent

はてなブックマーク 2 用に開発した本文抽出モジュール

HTML から「良い感じ」に本文テキストを抽出

CPAN に公開済 JavaScript 版を現在開発中

サイボウズ・ラボの中谷秀洋氏の Ruby 実装を Perl に移植

後述の検索、カテゴライズの精度に大きく影響

Page 18: はてなブックマークのシステムについて

HTML::ExtractContent の仕組み 正規表現だけで高速に ヒューリスティクスで " 本文らしさ " を判定

HTML を適当なブロック要素ごとに分割 各ブロックにスコアリング

本文っぽさでスコア増 ( 句読点、テキストノードの文字列長 etc) 本文っぽくなさでスコア減 ( リンクばかり並んでいる etc)

つながっているブロックをまとめてクラスタにする 高スコアが続いたらクラスタ、低スコアが来たら切れ目 ブロックスコアの合計がクラスタのスコア

スコアの一番高いクラスタが本文

詳しくは : http://d.hatena.ne.jp/tarao/20090322#1237750634

Page 19: はてなブックマークのシステムについて

HTML::LayeredExtractor ( 非公開 )

新聞など ・・・ ExtractContent で OK 一部のサイト ・・・ 確実に抜き出せる別の方法

<!-- google_ad_section_start --> Web API

ニコニコ動画、 YouTube 、 Amazon.co.jp

特定サイトはルールベースに処理 自社サイト、大手サイトは XPath で、など

フィードを利用 複数試して一番良い結果を選択するメタエンジン

Chain of Responsibility で順番に試して駄目なら ExtractContent に fallback

Page 20: はてなブックマークのシステムについて

全文検索機能

Page 21: はてなブックマークのシステムについて

2 つの全文検索システム

全登録文書からの全文検索 PFI の Sedue

自分のブックマークからの全文検索 有料オプション限定の機能 自社開発の Perl 検索エンジン

Page 22: はてなブックマークのシステムについて

1. 全文書からの全文検索

Sedue http://preferred.jp/sedue/ 圧縮 Suffix Arrays

スコアリングのアルゴリズム よく知られた幾つかのヒューリスティクス ブックマーク数やブックマークされた時間を加味

文書登録 , 更新 ブックマークのタイミングに合わせて

TheSchwartz で 1st ブックマークから数分後には検索可能

Page 23: はてなブックマークのシステムについて

2. 個人のブックマークからの全文検索 " マイブックマーク全文検索 " Perl で独自の全文検索システムを開発

オーソドックスな転置インデックス方式 ユーザー毎にインデックスを構築

動的に更新可能 id:naoya プロトタイプ → id:r_kurain ( 倉

井龍太郎 ), id:tarao が中心に開発

Page 24: はてなブックマークのシステムについて

転置インデックス

辞書 → 含む文書の ID 列 (Postings List) の索引

...perl => [1, 5, 20, 333, 350, 362 ...]python => [8, 10, 11, 52 ...]ruby => [1, 10, 21, 333, 350, 428 ...]...

Page 25: はてなブックマークのシステムについて

転置インデックスの構成

二つのインデックス 辞書が N-gram のインデックス

ノイズが少なく、且つ検索漏れして欲しくないデータ用のインデックス

タイトル、コメント、タグ、 URL 文字列など 辞書が形態素解析のインデックス

本文テキスト (by ExtractContent) などノイズの多い箇所 MeCab ( はてなキーワード + MeCab 辞書 )

検索は両者から行って、結果をマージ

Postings List には文書 ID と単語出現位置を記録 スニペットの表示やスコアリングに出現位置が必要 [ 10: 2, 100, 108, ... ]

Page 26: はてなブックマークのシステムについて

転置インデックスの構成 ( 続き )

転置インデックスの圧縮 Postings List の差分を取って VB 符号 ( 相当 ) Array::Gap

http://d.hatena.ne.jp/naoya/20080906/1220685978

転置インデックスの保存に Lux IO Lux の KVS Perl バインディング Lux::IO (id:antipop) シンプルで高速 ユーザー毎にファイルひとつ。本システムの運用に

最適 索引を作り直したかったらファイルを削除して再構築 分散したいなら、ユーザー ID などでパーティショニング

Page 27: はてなブックマークのシステムについて

検索結果のスコアリング

本夏のインターンシップで開発 id:yaotti, id:nyanp

Page 28: はてなブックマークのシステムについて

スコアリングの手法

複数のヒューリスティクスの結果を重み付き線形和で

(例 ) Score = 0.5 * TF-IDF + 0.2 * ブクマ数 + 0.3 * 新鮮度

重みは適当 本格的にやるなら正解データからの機械学習

Page 29: はてなブックマークのシステムについて

スコアリングの手法の一部 ( 続き )

クエリがタイトル等に含まれているかどうか 複数クエリ語の近傍度 クエリの出現位置 ・・・ 前半であるほど良 クエリのマッチの仕方 ( 単語境界かどうか etc) TF-IDF ブックマーク数 文書の新鮮度

文書の 1st ブックマーク日時 特定の URL にボーナス

Wikipedia, d.hatena.ne.jp/keyword など ルートドキュメント

Page 30: はてなブックマークのシステムについて

スコアリング今後

PageRank や HITS 的なリンク解析 クリックストリームからのフィードバッ

ク学習

Page 31: はてなブックマークのシステムについて

検索エンジンとアプリケーションのやりとり

JSON-RPC で Web API アクセス制限などはウェブアプリケーション側で

検索システムはあくまで検索結果を返すだけに専念

Web API は一般にも公開 google " マイブックマーク全文検索 API"

Page 32: はてなブックマークのシステムについて

Firefox 拡張 + マイブックマーク検索 拡張から Web API で検索結果を取得

Page 33: はてなブックマークのシステムについて

スペルミス修正機能

もしかして

Page 34: はてなブックマークのシステムについて

スペルミス修正サーバー

クエリ語に対して修正候補を返す C++ と Perl ・・・ Thrift

スコアリングエンジンを C++ で、問い合わせは Perl で

スペルミス修正のアルゴリズム はてなキーワードを辞書に補正 N-gram 索引を使って候補を絞り、 Jaro-Winkler 距離 (編集距離のようなもの ) で近似度を測定

詳しくは google "Kansai.pm スペルミス "

Page 35: はてなブックマークのシステムについて

関連エントリー機能

Page 36: はてなブックマークのシステムについて

レコメンドエンジン BSim

PFI のレコメンドエンジン ブックマークのタグを入力

ほかも幾つか試したがタグの精度が圧倒的に良かった

タグは記事推薦に非常に有効

Perl とのやりとり C++ で書かれたエンジンと Perl アプリ Thrift を利用して RPC で

Page 37: はてなブックマークのシステムについて

カテゴライズ機能

Page 38: はてなブックマークのシステムについて

文書分類エンジン BDog

自社開発の文書分類エンジン C++ で実装、 Thfirt で Perl から利用

本文テキスト (by ExtractContent) から単語ベクトルを作って判定

ベイジアンフィルタ Complement Naive Bayes

http://d.hatena.ne.jp/tkng/20081217/1229475900 特定のクラスに偏りがある場合、 Naive Bayes よりも精度

が向上 動的な学習により精度向上

ユーザーによるカテゴリ修正で ... 過学習防止のため対象は特定ユーザーに限定

Page 39: はてなブックマークのシステムについて

Complement Naive Bayes

Page 40: はてなブックマークのシステムについて

そのほか

ブックマークスパム判定機能 複数のルールベースを組合わせた判定エンジ

ン 例 : 同一順で同一エントリをブックマークし続け

る複数アカウントによるブックマーク

特徴語抽出 はてなキーワード TF-IDF 関連広告表示などにも利用

Page 41: はてなブックマークのシステムについて

各所で TheSchwartz を活用

TheSchwartz Six Apart 社開発のジョブキューフレームワーク CPAN

検索、スパム判定などブックマーク追加後に各種更新処理が発生

同期処理だとユーザーを待たせる TheSchwartz で非同期化

HTML を取得し本文抽出 / スパム判定 / カテゴリ判定 / Sedue への更新要求 / マイブックマーク検索エンジンへの更新要求 / はてなキーワード抽出 / リンク抽出 / favicon を取得 / AccountDiscovery / スクリーンショット撮影 ...

Page 42: はてなブックマークのシステムについて

はてなブックマーク Firefox 拡張

Page 43: はてなブックマークのシステムについて

Firefox 拡張

Firefox Add-ons XUL

http://subtech.g.hatena.ne.jp/secondlife/20090402/1238661633

id:secondlife, id:nanto_vi が中心に開発 オープンソース

http://github.com/hatena/hatena-bookmark-xul

はてなブックマークの各種機能を JSON API にして、 Firefox から利用

拡張用に追加した API の一部は公開 API としてもリリース

Page 44: はてなブックマークのシステムについて

雑感

Web + DB システムの一歩外の開発をここ一年ぐらいで色々した

検索、レコメンド、 Firefox 拡張 ... なかなか楽しい 新しい体験をエンドユーザーに提供できる

Page 45: はてなブックマークのシステムについて

パフォーマンスに関する話

Page 46: はてなブックマークのシステムについて

バックエンドのシステム構成

定番の三層構造 LVS + KeepAlived で分散 lighttpd or Apache -> (Squid ->)

mod_perl -> MySQL

Page 47: はてなブックマークのシステムについて

バックエンドシステムの三層構造

proxy proxy

LB

LB

app server app server app server app server

LB

DB DB

LB

LB

LB

Page 48: はてなブックマークのシステムについて

ハードウェア : 自作サーバー

Page 49: はてなブックマークのシステムについて

データベースの構成

オーソドックスな構成でスケーリング MySQL (MyISAM)

メモリ 16GB 一部で SSD を試験

マスタ・スレーブ構成 データのサイズ、用途に合わせてテーブル単

位で分割 メイン ( ユーザ情報、エントリ、ブックマーク ) タグ、キーワード HTML データ etc.

Page 50: はてなブックマークのシステムについて

島分け

proxy

AP

bot / feed

通常のリクエスト

DB

画像 API etc.

proxy

Page 51: はてなブックマークのシステムについて

Squid によるキャッシュ

Squid Reverse Proxy でキャッシュ ゲスト向けコンテンツ bot 向けコンテンツ 一部の API

○○ users 画像のバックエンドの API など

Page 52: はてなブックマークのシステムについて

memcached によるキャッシュ

アプリケーションフレームワークに memcached キャッシュ機能

ページを丸ごと memcached にキャッシュする機能

ユーザー毎の設定パラメータをまとめて SHA1 キーを作り、同じ設定のユーザーには同じキャッシュを返す機能

Template::Plugin::Cache longtail はキャッシュしない

○○ users を閾値に

Page 53: はてなブックマークのシステムについて

クライアント表示に関する工夫

昨今では定番の手法を実施 gzip 圧縮 静的ファイルの Expires を 1年に

更新される可能性のあるものは別ディレクトリで管理

CSS, JavaScript ファイルは git の commit + path の SHA1 をクエリパラメータに 例 : /js/foo.js?sha1hogehoge

静的ファイルを別ドメイン → Cookie 分の転送を削減

Page 54: はてなブックマークのシステムについて

クライアント表示に関する工夫 ( 続き )

JavaScript による遅延ロード 広告の遅延ロード

広告表示でページ表示が待たされない Google の広告、自社広告

Page 55: はてなブックマークのシステムについて

クライアント表示に関する工夫 ( 続き )

ユーザー毎に出し分ける部分を JS で遅延

残った共通部分 (HTML) をキャッシュできる

Page 56: はてなブックマークのシステムについて

雑感

一般的な Web + DB システムの運用は苦労が減った

ハードウェアの進歩、特にメモリ容量 各種ノウハウがウェブや書籍等で公開されている

JavaScript の遅延ロードをうまく使うと高速化に寄与できる箇所が多い

RDBMS だけでは難しい規模 / 要件をどうするかが面白い

検索エンジンを作る、レコメンドエンジンを作る、文書分類エンジンを作る ... etc.

Page 57: はてなブックマークのシステムについて

WEB+DB PRESS Vol.49

Page 58: はてなブックマークのシステムについて

まとめ

はてなブックマークのシステムの裏側を紹介した

オーソドックスな Web + DB システムと幾つかのサブシステムを開発した

検索、レコメンド、文書分類 etc RDBMS では難しい /面倒なことをどう解決していくかが今後もテーマに

Page 59: はてなブックマークのシステムについて

Thank You !