Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

ツイートID生成とツイッターリアルタイム検索システムの話

18,532 views

Published on

Published in: Technology
  • Be the first to comment

ツイートID生成とツイッターリアルタイム検索システムの話

  1. 1. PFIセミナー ツイートID生成とツイッターリアルタイム検索 システムの話 Eiichiro Iwata 2012年 12月20日
  2. 2. 自己紹介l 岩田 英一郎 (@eiichiroi) l 元さいたまな人l 経歴 l 2009年6月∼ アルバイト l 2010年3月  埼玉大学 大学院理工学研究科 修了 l 2010年8月∼ PFI入社l 所属 l 製品開発部 l Sedueプロジェクトl 仕事 l Sedue(検索エンジン)の開発 l コア∼運用ツールを幅広く l 研究開発成果の取り込み 2
  3. 3. 本日の内容l ツイートID生成システムSnowflakeの解説 l ツイートIDの構造と生成方法l リアルタイム検索システムEarlybirdの解説 l 5億ツイート/日(約6000ツイート/秒)で増え続けるツイートを即時 に検索できるシステム l アーキテクチャの概要 l インデックスの構成 3
  4. 4. 突然ですが 4
  5. 5. ツイッターIDの 生成方法を知っていますか? 5
  6. 6. これ6
  7. 7. 本題7
  8. 8. ツイートID生成システムSnowflakeとは l ユニークなIDを生成するネットワークサービス l ツイッターのツイートID(ステータスID)の割り当てに使われている l ツイッター社がOSSで公開中 (*) l 特徴 l 64 bitのIDを生成 l ざっくり時刻順 l 速い l 10000 ID/秒 のスピードでIDを生成できる(1プロセスあたり) l レスポンス 2 ms (+ネットワークのレイテンシ) l スケールする l 複数のマシン・プロセスで協調動作しない l 並べただけスケールする(はず)(*) https://github.com/twitter/snowflake 8
  9. 9. Snowflakeが開発されるまで l ツイートの流速増加とツイッターのシステム移行 l 5億ツイート/日(約6000ツイート/秒) (*1) l 2012年10月時点 l MySQLからCassandraやGizzard(Sharded MySQL)への移行 l CassandraがID生成をデフォルトで提供していない l ステータスIDの変遷 (*2, *3, *4) l 2006年5月∼: 符号付き32bit l 2009年6月∼: 符号無し32bit l 2009年9月∼: 64bit l 2010年11月∼: 64bit(現状のsnowflake) l 要求 l スケールする(分散できる)(*1) Report: Twitter hits half a billion tweets a day(*2) Twitpocalypse - TwitterメッセージIDの64ビット科- いよいよ明日に実施 9(*3) Status IDs are changing on 21st September(*4) Announcing Snowflake
  10. 10. 生成するIDの構造 41bit 10bit 12bit 時刻 マシンID 連番l 64bitを3つのブロックに分割 l 時刻(41bit、69年分) l (おそらく)snowflakeの運用開始時刻からの経過時間(ミリ秒) l 2010年11月4日...(epoch: 1288834974657)が基点 l マシンID(10bit、1024台分) l データセンターID(上位5bit)、ワーカーID(下位5bit) l 起動時にZookeeperか設定ファイルから取得 l 連番(12bit、4096個) l 同時刻・同マシンでのID重複回避用、ワーカー別l 参考: バルス砲 25088 ツイート/秒 10
  11. 11. ツイートIDのデコード(デモ)l ツイートID = 279622981959970816 l 時刻 = 1355502288700 (2012-12-15 01:24:48 +0900) l マシンID = 39 l データセンタID = 1 l ワーカーID = 7 l 連番 = 0 11
  12. 12. 生成するIDの特徴l 64bit整数l ユニークl 時間とともにIDの値が増加する l ステータスIDでざっくり時刻順にソートできる(k-sorted) l 目標精度は1秒 l 1秒以内に投稿されたツイート間では順序を保証しない l 実際の時刻順と逆になることもある 12
  13. 13. 生成するIDの特徴 - k-sorted l 系列α = (a1, ..., an) が k-sorted であるとは、 l 全ての 1 ≦ i, j ≦ n に対して、 i < j-k ならば ai ≦ aj k l 概要 a1 ... ai ... ai-k+1 ... an l 0-sortedは普通のソートと等価 l 距離 k 以内の要素間での順序は不問 l 例: (2, 1, 3)は1-sorted l k-sortedの性質 (*1, *2) l 系列αとkが与えられたときに、k-soterdかどうかはO(n)で判定可能 l 系列αが与えられたときに、最も小さいkの値をO(n)で計算可能 l 2つのk-sorted系列が与えられたときに、それらをマージした1つの k-sorted系列をO(n)で計算可能 l 系列αをk-sortedを満たすようにするには、O(n log k)で計算可能(*1) Roughly Sorting: A Generalization of Sorting 13(*2) Roughly Sorting: Sequential and Parallel Approach
  14. 14. 生成するIDの特徴 - k-sortedのkの値 41bit 10bit 12bit 時刻 マシンID 連番 l 複数のマシンで完全に同じ時刻を参照できたと仮定すると... l 222 -sorted: 22bit = 10bit(マシンID)+12bit(連番) l 精度: 1ミリ秒 l 232-sorted: 32bit = 約10bit(時刻)+10bit(マシンID)+12bit(連番) l 精度: 1秒 l 実際にはマシンID、連番が疎なので k はそこまで大きくないはず l 3000 ツイート/秒なら、連番は3くらい l NTPの精度はミリ秒単位 (*) l 現実的にはこちらの方が精度のネックになりそう l kの値自体にあまり意味はないはず 14(*) http://www2.nict.go.jp/aeri/sts/tsp/PubNtp/qa.html#q2-2
  15. 15. その他 l マシンIDや連番の実際の値 (*) l データセンターIDは1 l ワーカーIDは0∼4 l 連番は0∼2 l モノトニックタイム l 設定で変更できない単調増加な時刻 l linuxではclock_gettime()などで取得可能 l 時刻が巻き戻ると厄介 l IDの一意性を保証するのが面倒になる l snowflakeでは巻き戻りが発生したときはエラー l 最後にIDを生成した時刻を記憶しておくだけ(*) はてな匿名ダイアリー snowflakeの実際 15
  16. 16. ツイートID生成システムSnowflakeとは(再掲) l ユニークなIDを生成するネットワークサービス l ツイッターのツイートID(ステータスID)の割り当てに使われている l ツイッター社がOSSで公開中 (*) l 特徴 l 64 bitのIDを生成 l ざっくり時刻順 l 速い l 10000 ID/秒 のスピードでIDを生成できる(1プロセスあたり) l レスポンス 2 ms (+ネットワークのレイテンシ) l スケールする l 複数のマシン・プロセスで協調動作しない l 並べただけスケールする(はず)(*) https://github.com/twitter/snowflake 16
  17. 17. リアルタイム検索システムEarlybirdの概要l ツイッターリアルタイム検索エンジン l Java製 l オープンソースの全文検索ライブラリLuceneを魔改造 l 転置インデックス l クエリ言語(Boolean query) l AND/OR/NOT l フレーズクエリ l ワイルドカードクエリは未対応 l 2010年10月にMySQLベースの検索システムから移行l 出典 l Earlybird: Real-Time Search at Twitter, ICDE 2012 l Michael Busch, Krishna Gade, Brian Larson, Patrick Lok, Samuel Luckenbill, and Jimmy Lin 17
  18. 18. Earlybirdの性能の実績値l ツイートの登録速度 l 3000 ツイート/秒 (2012年10月時点で6000 ツイート/秒)l ツイート登録後すぐに検索可能に l ∼10秒以内 l ※検索対象は6∼9日以内のツイートのみl 検索性能 l 低レイテンシ(平均50 ms) l 高スループット(20億件/日 ≒ 2300qps) 18
  19. 19. Earlybirdのアーキテクチャ • • ツイートのトークナイズ メタ情報(言語など)を付与 • 動的更新の通知 • リツイート数の更新 • お気に入りの更新 • ...• 登録先のツイート • ハッシュでパーティション • ハッシュの方式は不明• ツイートの検索 • クエリのパース• ランキング • 複数のEarlybirdへ問い合わせ • リツイート数 • Userのローカルソーシャルグラフを渡す • お気に入り数 • 問い合わせ結果のマージ • ... • Userのローカルソーシャルグラフ 19
  20. 20. • 更新するインデックスを限定Earlybirdの構成 • 1億件/台 • 12インデックス/台 • マシンスペック Earlybird • クアッドコア2つ • RAM 72GB • 64GBをJVMのヒープに割当 ... Optimized Index(11個) Active Index(1個) • 検索(読込)専用 • 検索(読込)+文書登録(書込) • 224 ≒ 1600万件/インデックス • 更新が速いデータ構造 • 圧縮(圧縮率55%程度) • 一杯になったら裏で最適化 • 1600万件で3.7GB程度 • 1600万件で6.7GB程度 20
  21. 21. 辞書の構成(1/2)l 辞書 l 単語とPosting List(その単語を含む文書IDのリスト)を紐付けるl 自作ハッシュテーブルで実装 l オープンアドレス法をArrayで実装 l Java標準のHashMapはGCと相性が悪い l チェーンで繋いだオブジェクト達の寿命が長いl 辞書に含める情報 l (0) 単語ID l (1) その単語のPosting Listの長さ l (2) その単語のPosting Listの末尾へのポインタ l ※それぞれ別々の配列で管理(詳細は次スライド) l 単語IDを配列のインデックスとしてアクセスする l 速度とメモリ効率を上げるため(Java...) 21
  22. 22. 辞書の構成(2/2) 辞書 自作ハッシュテーブル 単語の数 単語 単語ID 0 1 ...pfiseminar 0 (1) Posting Listの長さ 4 77 ...なう 1 (2) 末尾へのポインタ ... : : 転置インデックス 4 「pfiseminar」に対応するPosting List ... ... ... ... 77 「なう」に対応するPosting List ... ... : : 22
  23. 23. Active Indexl 要求 l 文書登録(書込)処理が高速 (全サーバで6000ツイート/秒) l 検索(読込)処理も並列処理 l 時刻降順に検索したい (とにかく最近の情報が重要)l 特徴 l (1) Posting Listは文書ID昇順 l (2) Postingは32bit整数 l (3) Posting Listのメモリはまとめて確保l 削除の対応方法は不明 l 削除フラグを持ってフィルタリングしているとか? 23
  24. 24. Active Index - (1) Posting Listは文書ID昇順l 利点 l 文書登録時には、Posting Listの末尾に追加するだけ 文書ID: 15 pfiseminar 2 7 11 15 pfiseminar なう l 検索時には、Posting Listの末尾から逆順に るだけ pfiseminar 2 7 11 15 pfiseminarl 欠点 l Posting Listの差分圧縮と相性が悪い l 検索時にPosting Listを逆順に れる差分圧縮は複雑 ‒ ブロックベースのPForDelataとか l 文書登録のレイテンシが増加 l Active IndexでのPosting List圧縮は諦め 24
  25. 25. Active Index - (2) Postingは32bit整数 ※ビットレイアウトは違うかも 8bit 24bit 単語位置 文書IDl 文書ID(24bit) l 1インデックス辺り224(≒ 1600万)件が上限l 単語位置(8bit) l 140文字なので8bitで十分 l 1件にある単語が複数回出現するときは、別のPostingとして扱うl 利点 l コンパクト l Posting Listが整数配列になり、メモリの事前割り当てが容易 l ブロック単位でまとめて割り当てちゃう l キャッシュにも優しい 25
  26. 26. Active Index - (3) Posting Listのメモリはまとめてpool 3pool 2pool 1pool 0 l 4種類のpool l 1poolあたり215 posting(必要に応じて拡張)、複数のsliceからなる l sliceのサイズが異なる(21, 24, 27, 211) l sliceを繋げて長いPosting Listを実現 l sliceのサイズが小さい方から、slice単位で順に割り当てて行く l sliceの最初の要素は、前のsliceの末尾へのポインタ(32bit) l 文書集合中の単語の分布はジップの法則でモデル化している l 長いPosting Listが少数、短いPosting Listが多数 l 工夫しないとメモリ効率が悪く速度が遅くなってしまう 26 l この実装では、Posting Listの拡張時にメモリコピーが発生しない
  27. 27. Active Index - (3) Posting Listのメモリはまとめて ※ビットレイアウトは違うかも 11bit 19bit 2bitpool 3 offset in slice slice index 11 7bit 23bit 2bitpool 2 offset in slice slice index 10 4bit 26bit 2bitpool 1 offset slice index 01 1bit 29bit 2bitpool 0 o slice index 00 pool index l sliceのポインタ 27 l 32bitでpostingと同じサイズ
  28. 28. Optimized Indexl 要求 l 検索(読込)処理のみ l 文書登録(書込)処理は受け付けないl 特徴 l Active Indexが一杯(223件)になったら裏でOptimized Indexを構築 l Optimized Index構築後、スワップ(古いインデックスは削除) l 短いPosting Listは時刻降順にソート l 検索時には先頭から順方向に る l 長いPosting List(長さ1000以上)はブロック単位で圧縮 l PForDeltaやSimple9と似たような感じ l Active Indexの55%くらいのメモリ使用量 l 1600万件6.7GBが3.7GB程度に 28
  29. 29. Optimized Index - 長いPosting Listの圧縮4byte 4byte 248byte 4byte 4byteposting header (文書IDの差分, 単語位置)の組n個を圧縮したもの posting header ... 256byte/block l 時刻降順のPosting Listを適当に区切ってブロック単位で圧縮 l 固定長ブロック256byteを複数並べたもの l 先頭4byte: ブロックのスキップ用 l ブロック先頭の生posting1つ l 次の4byte: ブロックのヘッダ(解凍時に必要) l 圧縮されている文書数 n l 圧縮のビット幅 b = ceil(max(gap)) + ceil(max(pos)) ‒ n * (ceil(max(gap)) + ceil(max(pos))) <= 1984(= 248*8) l 残り248byte: 圧縮 l n個の(文書IDの差分, 単語位置)の組を圧縮したもの 29
  30. 30. まとめl ツイートID生成システムSnowflakeの解説 l ツイートID構造と生成方法 l ざっくり時刻順、速い、スケールl リアルタイム検索システムEarlybirdの解説 l 5億ツイート/日(約6000ツイート/秒)で増え続けるツイートを即時 に検索できるシステム l アーキテクチャの概要 l インデックスの構成 l Active Index l Optimized Index 30
  31. 31. Copyright © 2006-2012Preferred Infrastructure All Right Reserved.

×