39
100ぐらいで書く分散検索エンジ Hadoop + Lucene 太田一樹 <[email protected]>

Hadoop @ Java CCC 2008 Spring

Embed Size (px)

Citation preview

Page 1: Hadoop @ Java CCC 2008 Spring

100行ぐらいで書く分散検索エンジン

Hadoop + Lucene

太田一樹

<[email protected]>

Page 2: Hadoop @ Java CCC 2008 Spring

自己紹介

• 太田一樹

– http://kzk9.net/

– 東京大学情報理工学系研究科コンピューター科学専攻石川研究室

Page 3: Hadoop @ Java CCC 2008 Spring

今回のテーマ

• Javaで分散検索エンジンを楽をして作る

– Lucene (検索エンジン)

– Hadoop (MapReduceフレームワーク)

• 個人でも大規模な検索エンジンがさくっと作れる時代ということを示してみる

Page 4: Hadoop @ Java CCC 2008 Spring

Agenda

• Luceneの説明

• Hadoopの説明

• Lucene + Hadoopで検索エンジンを構築

• まとめ

Page 5: Hadoop @ Java CCC 2008 Spring

(Lucene)とは?

• Javaで書かれた検索エンジン– Yahoo ResearchのDougCutting氏が開発

– Javaのクラスライブラリとして提供され、他のソフトウェアから簡単に使用可能

– 文章サイズにもよるが、数百万件程度なら1台で検索可能

• 検索できるようになるまでの流れ– 文章を登録し、検索用インデックスを作成

– 検索用インデックスを読み込み、クエリーを発行

Page 6: Hadoop @ Java CCC 2008 Spring

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("url", filepath[i]));Reader reader = new FileReader(filepath[i]);//文書内容の登録doc.add(Field.Text("contents",reader));writer.addDocument(doc);

} //インデクサのクローズwriter.optimize(); writer.close();

Page 7: Hadoop @ Java CCC 2008 Spring

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("url", filepath[i]));Reader reader = new FileReader(filepath[i]);//文書内容の登録doc.add(Field.Text("contents",reader));writer.addDocument(doc);

} //インデクサのクローズwriter.optimize(); writer.close();

Page 8: Hadoop @ Java CCC 2008 Spring

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("url", filepath[i]));Reader reader = new FileReader(filepath[i]);//文書内容の登録doc.add(Field.Text("contents",reader));writer.addDocument(doc);

} //インデクサのクローズwriter.optimize(); writer.close();

Page 9: Hadoop @ Java CCC 2008 Spring

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("url", filepath[i]));Reader reader = new FileReader(filepath[i]);//文書内容の登録doc.add(Field.Text("contents",reader));writer.addDocument(doc);

} //インデクサのクローズwriter.optimize(); writer.close();

Page 10: Hadoop @ Java CCC 2008 Spring

Lucene検索サンプル

// インデックス読み込みIndexSearcher is = new IndexSearcher("index");// クエリーパーサーの作成QueryParser qp = new QueryParser("content", new SimpleAnalyzer());// 検索クエリーの準備Query q = qp.parse(“SomeQuery");// 検索を実行Hits hs = is.search(q);// 検索結果を表示System.out.println(hs.length() + " hit(s)");for(int i=0; i<hs.length(); i++) {

System.out.println(hs.doc(i).toString()); }is.close();

Page 11: Hadoop @ Java CCC 2008 Spring

Hadoopとは?

• Googleの基盤ソフトウェアのクローン

– Google File System

– MapReduce

• Yahoo Research の Doug Cutting氏が開発

– 元々はNutch Crawlerのサブプロジェクト

– Dougの子供の持っているぬいぐるみの名前

• Javaで記述

Page 12: Hadoop @ Java CCC 2008 Spring

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

Page 13: Hadoop @ Java CCC 2008 Spring

MapReduceの実行フロー

Data Map

Data Map

Data Map

Reduce

Reduce

Data

Data

Shuffle

Page 14: Hadoop @ Java CCC 2008 Spring

Hadoopのスケーラビリティ

• Scaling 4000 nodes at Yahoo!

– http://developer.yahoo.net/blogs/hadoop/2008/09/scaling_hadoop_to_4000_nodes_a.html

• Hadoop wins Terabyte Sort Benchmark

– http://developer.yahoo.net/blogs/hadoop/2008/07/apache_hadoop_wins_terabyte_sort_benchmark.html

• Hadoopで書いとけば、4000ノードぐらいまではスケールするよ!

Page 15: Hadoop @ Java CCC 2008 Spring

例: ワードカウント

Data Map

Data Map

Data Map

Reduce

Reduce

Data

Data

Shuffle

foo foo foobar bar buzz

入力文書: doc1

Page 16: Hadoop @ Java CCC 2008 Spring

例: ワードカウント

Data Map

Data Map

Data Map

Reduce

Reduce

Data

Data

Shuffle

foo foo foobar bar buz

入力文書: doc1

doc1: foodoc1: foo

doc1: foodoc1: bar

doc1: bardoc1: buz

Page 17: Hadoop @ Java CCC 2008 Spring

例: ワードカウント

Data Map

Data Map

Data Map

Reduce

Reduce

Data

Data

Shuffle

foo foo foobar bar buz

入力文書: doc1

doc1: foodoc1: bar

doc1: bardoc1: buz

doc1: foodoc1: foo

Page 18: Hadoop @ Java CCC 2008 Spring

例: ワードカウント

Data Map

Data Map

Data Map

Reduce

Reduce

Data

Data

foo foo foobar bar buz

入力文書: doc1

doc1: foodoc1: bar

doc1: bardoc1: buz

doc1: foodoc1: foo

foo: 1foo: 1

bar: 1foo: 1

bar: 1buz: 1

Page 19: Hadoop @ Java CCC 2008 Spring

例: ワードカウント

Data Map

Data Map

Data Map

Reduce

Reduce

Data

Data

foo foo foobar bar buz

入力文書: doc1

foo: 1foo: 1

bar: 1foo: 1

bar: 1buz: 1

bar: <1, 1>buz: <1>

foo: <1, 1, 1>

Page 20: Hadoop @ Java CCC 2008 Spring

例: ワードカウント

Data Map

Data Map

Data Map

Reduce

Reduce

Data

Data

foo foo foobar bar buz

入力文書: doc1

bar: <1, 1>buz: <1>

foo: <1, 1, 1>

Page 21: Hadoop @ Java CCC 2008 Spring

例: ワードカウント

Data Map

Data Map

Data Map

Reduce

Reduce

Data

Data

foo foo foobar bar buz

入力文書: doc1

foo: <1, 1, 1>

bar: <1, 1>buz: <1>

foo: 3

bar: 2buz: 1

Page 22: Hadoop @ Java CCC 2008 Spring

例: ワードカウント

Data Map

Data Map

Data Map

Reduce

Reduce

Data

Data

foo foo foobar bar buz

入力文書: doc1

bar: 2buz: 1

foo: 3

Page 23: Hadoop @ Java CCC 2008 Spring

作成する検索エンジンの仕組み

url1: <html>…url2: <html>…url3: <html>…url4: <html>…url5: <html>…url6: <html>…url7: <html>…

クロールしてきた文章 Lucene

インデックス1

Lucene

インデックス2

Lucene

インデックス3

Lucene

インデックス4

Lucene

インデックス5

Hadoopによる分散インデックス

作成

分散クエリー発行

検索用ノード

Page 24: Hadoop @ Java CCC 2008 Spring

Hadoopによる分散インデックス作成

Data Map

Data Map

Data Map

Reduce

Reduce

Data

Data

Shuffleurl3: <html>…url4: <html>…

url1: <html>…url2: <html>…

url5: <html>…url6: <html>…

Page 25: Hadoop @ Java CCC 2008 Spring

Hadoopによる分散インデックス作成

Data Map

Data Map

Data Map

Reduce

Reduce

Data

Data

Shuffleurl3: <html>…url4: <html>…

url1: <html>…url2: <html>…

url5: <html>…url6: <html>…

Page 26: Hadoop @ Java CCC 2008 Spring

Hadoopによる分散インデックス作成

Data Map

Data Map

Data Map

Reduce

Reduce

Data

Data

Shuffleurl3: <html>…url4: <html>…

url1: <html>…url2: <html>…

url5: <html>…url6: <html>…

url1: <html>…url4: <html>…url5: <html>…

url2: <html>…url3: <html>…url6: <html>…

Page 27: Hadoop @ Java CCC 2008 Spring

Hadoopによる分散インデックス作成

Data Map

Data Map

Data Map

Reduce

Reduce

Data

Data

Shuffle

url1: <html>…url4: <html>…url5: <html>…

url2: <html>…url3: <html>…url6: <html>…

Lucene

インデックス

Lucene

インデックス

Page 28: Hadoop @ Java CCC 2008 Spring

Hadoopによる分散インデックス作成

Data Map

Data Map

Data Map

Reduce

Reduce

Data

Data

Shuffle

Lucene

インデックス

Lucene

インデックス

Page 29: Hadoop @ Java CCC 2008 Spring

Hadoopによる分散インデックス作成

Data Map

Data Map

Data Map

Reduce

Reduce

Data

Data

Shuffle

Lucene

インデックス

Lucene

インデックス

Page 30: Hadoop @ Java CCC 2008 Spring

Hadoopによる分散インデックス作成

Data Map

Data Map

Data Map

Reduce

Reduce

Data

Data

Shuffle

Lucene

インデックス

Lucene

インデックス

Page 31: Hadoop @ Java CCC 2008 Spring

分散インデックス作成(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);

}

Page 32: Hadoop @ Java CCC 2008 Spring

分散インデックス作成(Reduceフェーズ)

public void reduce(Text key, Iterator<Text> values,OutputCollector<Text, Writable> output,Reporter reporter) throws IOException {

// URLText url = key;// 本文Text str = values.next();// ドキュメントを追加Document doc = new Document();doc.add(new Field("url", url.toString(), Field.Store.YES, Field.Index.NO));doc.add(new Field("content", str.toString(), Field.Store.YES, Field.Index.TOKENIZED));output.collect(url, new LuceneDocumentWrapper(doc));

}

Page 33: Hadoop @ Java CCC 2008 Spring

分散インデックス作成(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;

} }

Page 34: Hadoop @ Java CCC 2008 Spring

以上のコードを実行

• Hadoopのインストール

– 今回は24 (dual core)台のクラスタを使用

• ビルド

• 実行

– bin/hadoop jar indexer.ja net.kzk9.indexer in out

• 分散ファイルシステムのoutというディレクトリにLuceneインデックスが作成されている

– 30Gのドキュメントで約2-3時間?

Page 35: Hadoop @ Java CCC 2008 Spring

作成する検索エンジンの仕組み

url1: <html>…url2: <html>…url3: <html>…url4: <html>…url5: <html>…url6: <html>…url7: <html>…

クロールしてきた文章 Lucene

インデックス1

Lucene

インデックス2

Lucene

インデックス3

Lucene

インデックス4

Lucene

インデックス5

Hadoopによる分散インデックス

作成

分散クエリー発行

検索用ノード

ここを作った

Page 36: Hadoop @ Java CCC 2008 Spring

落ち穂拾い

• 時間的にここまで

• 残りのタスク

– クエリー受け付け用のサーバーを用意

– 作成されたインデックスをそいつらに転送

– クライアントから各サーバーにクエリーを発行

Page 37: Hadoop @ Java CCC 2008 Spring

とはいえ

• 商用検索エンジンにするには絶対的に欠けている要素– ランキング

– クローラー

• OSSの分散検索エンジン– Nutch

• OSSの検索エンジン

• あんまり出来が良くない

– Senna• 分散バージョンマダー?

Page 38: Hadoop @ Java CCC 2008 Spring

まとめ

• Luceneの使い方を説明

• Hadoopの使い方を説明

• 組み合わせて分散でインデックスを作成する方法を紹介

Page 39: Hadoop @ Java CCC 2008 Spring

おわり

% wc -l indexer.java145 indexer.java