Hadoop @ Java CCC 2008 Spring

2,358 views

Published on

Hadoop @ Java CCC 2008 Spring

  • Be the first to comment

  • Be the first to like this

Hadoop @ Java CCC 2008 Spring

  1. 1. 100行ぐらいで書く分散検索エンジ ン Hadoop + Lucene 太田一樹 <kzk@il.is.s.u-tokyo.ac.jp>
  2. 2. 自己紹介 • 太田一樹 – http://kzk9.net/ – 東京大学情報理工学系研究科コンピューター 科学専攻石川研究室
  3. 3. 今回のテーマ • Javaで分散検索エンジンを楽をして作る – Lucene (検索エンジン) – Hadoop (MapReduceフレームワーク) • 個人でも大規模な検索エンジンがさくっ と作れる時代ということを示してみる
  4. 4. Agenda • Luceneの説明 • Hadoopの説明 • Lucene + Hadoopで検索エンジンを構築 • まとめ
  5. 5. (Lucene)とは? • Javaで書かれた検索エンジン – Yahoo ResearchのDougCutting氏が開発 – Javaのクラスライブラリとして提供され、他 のソフトウェアから簡単に使用可能 – 文章サイズにもよるが、数百万件程度なら1 台で検索可能 • 検索できるようになるまでの流れ – 文章を登録し、検索用インデックスを作成 – 検索用インデックスを読み込み、クエリーを 発行
  6. 6. Luceneインデックス作成サンプ ル //インデックスに登録するファイルのあるディレクトリ File directory = new File(args[0]); String[] filepath = directory.list(); //インデックスの保存先 String index = args[1]; //インデクサの生成 IndexWriter writer = new IndexWriter(index, new JapaneseAnalyzer(), true); //文書の解析 for (int i = 0; i < filepath.length; i++) { Document doc = new Document(); //ファイルの登録 doc.add(Field.UnIndexed(quot;urlquot;, filepath[i])); Reader reader = new FileReader(filepath[i]); //文書内容の登録 doc.add(Field.Text(quot;contentsquot;,reader)); writer.addDocument(doc); } //インデクサのクローズ writer.optimize(); writer.close();
  7. 7. Luceneインデックス作成サンプ ル //インデックスに登録するファイルのあるディレクトリ File directory = new File(args[0]); String[] filepath = directory.list(); //インデックスの保存先 String index = args[1]; //インデクサの生成 IndexWriter writer = new IndexWriter(index, new JapaneseAnalyzer(), true); //文書の解析 for (int i = 0; i < filepath.length; i++) { Document doc = new Document(); //ファイルの登録 doc.add(Field.UnIndexed(quot;urlquot;, filepath[i])); Reader reader = new FileReader(filepath[i]); //文書内容の登録 doc.add(Field.Text(quot;contentsquot;,reader)); writer.addDocument(doc); } //インデクサのクローズ writer.optimize(); writer.close();
  8. 8. Luceneインデックス作成サンプ ル //インデックスに登録するファイルのあるディレクトリ File directory = new File(args[0]); String[] filepath = directory.list(); //インデックスの保存先 String index = args[1]; //インデクサの生成 IndexWriter writer = new IndexWriter(index, new JapaneseAnalyzer(), true); //文書の解析 for (int i = 0; i < filepath.length; i++) { Document doc = new Document(); //ファイルの登録 doc.add(Field.UnIndexed(quot;urlquot;, filepath[i])); Reader reader = new FileReader(filepath[i]); //文書内容の登録 doc.add(Field.Text(quot;contentsquot;,reader)); writer.addDocument(doc); } //インデクサのクローズ writer.optimize(); writer.close();
  9. 9. Luceneインデックス作成サンプ ル //インデックスに登録するファイルのあるディレクトリ File directory = new File(args[0]); String[] filepath = directory.list(); //インデックスの保存先 String index = args[1]; //インデクサの生成 IndexWriter writer = new IndexWriter(index, new JapaneseAnalyzer(), true); //文書の解析 for (int i = 0; i < filepath.length; i++) { Document doc = new Document(); //ファイルの登録 doc.add(Field.UnIndexed(quot;urlquot;, filepath[i])); Reader reader = new FileReader(filepath[i]); //文書内容の登録 doc.add(Field.Text(quot;contentsquot;,reader)); writer.addDocument(doc); } //インデクサのクローズ writer.optimize(); writer.close();
  10. 10. Lucene検索サンプル // インデックス読み込み IndexSearcher is = new IndexSearcher(quot;indexquot;); // クエリーパーサーの作成 QueryParser qp = new QueryParser(quot;contentquot;, new SimpleAnalyzer()); // 検索クエリーの準備 Query q = qp.parse(“SomeQueryquot;); // 検索を実行 Hits hs = is.search(q); // 検索結果を表示 System.out.println(hs.length() + quot; hit(s)quot;); for(int i=0; i<hs.length(); i++) { System.out.println(hs.doc(i).toString()); } is.close();
  11. 11. Hadoopとは? • Googleの基盤ソフトウェアのクローン – Google File System – MapReduce • Yahoo Research の Doug Cutting氏が開発 – 元々はNutch Crawlerのサブプロジェクト – Dougの子供の持っているぬいぐるみの名前 • Javaで記述
  12. 12. Hadoop参考文献 • Hadoop公式サイト – http://hadoop.apache.org/core/ – Wiki: http://wiki.apache.org/hadoop/ • インストール方法・チュートリアル・プレゼン資 料など • Hadoop解析資料 (拙著) • http://preferred.jp/pub/hadoop.html • Hadoop, hBaseで構築する大規模データ処 理システム on CodeZine (拙著) – http://codezine.jp/a/article/aid/2448.aspx
  13. 13. MapReduceの実行フロー Map Data Reduce Data Shuffle Map Data Reduce Data Map Data
  14. 14. Hadoopのスケーラビリティ • Scaling 4000 nodes at Yahoo! – http://developer.yahoo.net/blogs/hadoop/2008/09/sc aling_hadoop_to_4000_nodes_a.html • Hadoop wins Terabyte Sort Benchmark – http://developer.yahoo.net/blogs/hadoop/2008/07/a pache_hadoop_wins_terabyte_sort_benchmark.html • Hadoopで書いとけば、4000ノードぐらいま ではスケールするよ!
  15. 15. 例: ワードカウント 入力文書: doc1 foo foo foo bar bar buzz Map Data Reduce Data Shuffle Map Data Reduce Data Map Data
  16. 16. 例: ワードカウント 入力文書: doc1 foo foo foo bar bar buz Map Data doc1: foo Reduce Data doc1: foo Shuffle Map Data doc1: foo Reduce doc1: bar Data Map Data doc1: bar doc1: buz
  17. 17. 例: ワードカウント 入力文書: doc1 foo foo foo bar bar buz doc1: foo doc1: foo Map Data Reduce Data doc1: foo doc1: bar Shuffle Map Data Reduce doc1: bar Data doc1: buz Map Data
  18. 18. 例: ワードカウント 入力文書: doc1 foo foo foo bar bar buz doc1: foo foo: 1 doc1: foo foo: 1 Map Data Reduce Data doc1: foo bar: 1 doc1: bar foo: 1 Map Data Reduce doc1: bar bar: 1 Data doc1: buz buz: 1 Map Data
  19. 19. 例: ワードカウント 入力文書: doc1 foo foo foo bar bar buz foo: 1 foo: 1 bar: <1, 1> Map Data buz: <1> Reduce Data bar: 1 foo: 1 Map Data foo: <1, 1, 1> Reduce bar: 1 Data buz: 1 Map Data
  20. 20. 例: ワードカウント 入力文書: doc1 foo foo foo bar bar buz bar: <1, 1> Map Data buz: <1> Reduce Data Map Data foo: <1, 1, 1> Reduce Data Map Data
  21. 21. 例: ワードカウント 入力文書: doc1 foo foo foo bar bar buz bar: <1, 1> bar: 2 Map Data buz: <1> buz: 1 Reduce Data Map Data foo: <1, 1, 1> foo: 3 Reduce Data Map Data
  22. 22. 例: ワードカウント 入力文書: doc1 foo foo foo bar bar buz bar: 2 Map Data buz: 1 Reduce Data Map Data foo: 3 Reduce Data Map Data
  23. 23. 作成する検索エンジンの仕組み 検索用ノード Lucene クロールしてきた文章 インデック ス1 Lucene url1: <html>… インデック url2: <html>… ス2 url3: <html>… Lucene Hadoopによる url4: <html>… 分散 インデック 分散インデックス url5: <html>… クエリー ス3 作成 url6: <html>… 発行 Lucene url7: <html>… インデック … ス4 Lucene インデック ス5
  24. 24. Hadoopによる分散インデックス作 成 url1: <html>… Map Data url2: <html>… Reduce Data url3: <html>… Shuffle Map Data url4: <html>… Reduce Data url5: <html>… Map Data url6: <html>…
  25. 25. Hadoopによる分散インデックス作 成 url1: <html>… Map Data url2: <html>… Reduce Data url3: <html>… Shuffle Map Data url4: <html>… Reduce Data url5: <html>… Map Data url6: <html>…
  26. 26. Hadoopによる分散インデックス作 成 url1: <html>… Map Data url2: <html>… url1: <html>… url4: <html>… Reduce Data url5: <html>… url3: <html>… Shuffle Map Data url4: <html>… url2: <html>… Reduce url3: <html>… Data url6: <html>… url5: <html>… Map Data url6: <html>…
  27. 27. Hadoopによる分散インデックス作 成 url1: <html>… Lucene url4: <html>… インデック Map Data url5: <html>… ス Reduce Data url2: <html>… Lucene Shuffle<html>… Map Data url3: インデック url6: <html>… ス Reduce Data Map Data
  28. 28. Hadoopによる分散インデックス作 成 Lucene インデック Map Data ス Reduce Data Lucene Shuffle Map Data インデック ス Reduce Data Map Data
  29. 29. Hadoopによる分散インデックス作 成 Lucene インデック Map Data ス Reduce Data Lucene インデック Shuffle Map Data ス Reduce Data Map Data
  30. 30. Hadoopによる分散インデックス作 成 Lucene Map Data インデック ス Reduce Data Lucene Shuffle Map Data インデック ス Reduce Data Map Data
  31. 31. 分散インデックス作成 (Mapフェーズ) // 何もしない public void map(Text key, Text value, OutputCollector<Text, Text> output, Reporter reporter) throws IOException { Text url = key; Text str = value; output.collect(url, str); }
  32. 32. 分散インデックス作成 (Reduceフェーズ) public void reduce(Text key, Iterator<Text> values, OutputCollector<Text, Writable> output, Reporter reporter) throws IOException { // URL Text url = key; // 本文 Text str = values.next(); // ドキュメントを追加 Document doc = new Document(); doc.add(new Field(quot;urlquot;, url.toString(), Field.Store.YES, Field.Index.NO)); doc.add(new Field(quot;contentquot;, str.toString(), Field.Store.YES, Field.Index.TOKENIZED)); output.collect(url, new LuceneDocumentWrapper(doc)); }
  33. 33. 分散インデックス作成 (Reduce終了フェーズ) public void close(final Reporter reporter) throws IOException { // 分散ファイルシステムに保存するための何か final Path perm = new Path(job.getOutputPath(), name); final Path temp = job.getLocalPath( “index/_” + Integer.toString(new Random().nextInt())); // インデックス作成 final IndexWriter writer = new IndexWriter( fs.startLocalOutput(perm, temp).toString(), new JapaneseAnalyzer(), true); try { writer.optimize(); writer.close(); fs.completeLocalOutput(perm, temp); // copy to dfs } finally { closed = true; } }
  34. 34. 以上のコードを実行 • Hadoopのインストール – 今回は24 (dual core)台のクラスタを使用 • ビルド • 実行 – bin/hadoop jar indexer.ja net.kzk9.indexer in out • 分散ファイルシステムのoutというディレ クトリにLuceneインデックスが作成されて いる – 30Gのドキュメントで約2-3時間?
  35. 35. 作成する検索エンジンの仕組み 検索用ノード Lucene クロールしてきた文章 インデック ここを作った ス1 Lucene url1: <html>… インデック url2: <html>… ス2 url3: <html>… Lucene Hadoopによる url4: <html>… 分散 インデック 分散インデックス url5: <html>… クエリー ス3 作成 url6: <html>… 発行 Lucene url7: <html>… インデック … ス4 Lucene インデック ス5
  36. 36. 落ち穂拾い • 時間的にここまで • 残りのタスク – クエリー受け付け用のサーバーを用意 – 作成されたインデックスをそいつらに転送 – クライアントから各サーバーにクエリーを発 行
  37. 37. とはいえ • 商用検索エンジンにするには絶対的に欠 けている要素 – ランキング – クローラー • OSSの分散検索エンジン – Nutch • OSSの検索エンジン • あんまり出来が良くない – Senna • 分散バージョンマダー?
  38. 38. まとめ • Luceneの使い方を説明 • Hadoopの使い方を説明 • 組み合わせて分散でインデックスを作成 する方法を紹介
  39. 39. おわり % wc -l indexer.java 145 indexer.java

×