Scala on Hadoop
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

Scala on Hadoop

on

  • 9,280 views

 

Statistics

Views

Total Views
9,280
Views on SlideShare
7,220
Embed Views
2,060

Actions

Likes
9
Downloads
110
Comments
0

10 Embeds 2,060

http://d.hatena.ne.jp 1863
http://blog.stanaka.org 95
http://stanaka.hatenablog.com 57
http://www.slideshare.net 32
http://webcache.googleusercontent.com 6
http://www.techgig.com 2
http://74.125.153.132 2
http://cache.yahoofs.jp 1
http://www.copyscape.com 1
http://translate.googleusercontent.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Scala on Hadoop Presentation Transcript

  • 1. Hadoop Conference Scala on Hadoop はてな 田中 慎司 stanaka @ hatena.ne.jp http://d.hatena.ne.jp/stanaka/ http://twitter.com/stanaka/
  • 2. アジェンダ
    • 自己紹介
    • はてなでの Hadoop
      • Scala までの道
    • Scala on Hadoop
    • Scala on Hadoop の応用
  • 3. 自己紹介
    • ( 株 ) はてな 執行役員
    • 担当領域
      • システムアーキテクチャ
        • スケーラビリティ
      • サーバ・ネットワーク
      • サポート
  • 4. はてなでの Hadoop #1
    • 自作サーバ 10 台
      • CPU: Core2 Quad x 1
      • Mem: 8GB
      • HDD: 3TB
    • DC ではなくオフィスに置いて、電源代節約
  • 5. はてなでの Hadoop #2
    • 蓄積されるデータ ( 主にログ )
      • ダイアリー 7G/day
      • ブックマーク 5G/day
      • うごメモ 3G/day
    • ジョブ
      • 300 jobs/day
  • 6. はてなでの Hadoop システム ( 現状 ) Hadoop MapReduce HDFS Reverse Proxy ジョブの 投入 Hatena Fotolife Hatena Graph ログを 時間毎に蓄積 /logs/$service/$year/$month/$date/$host_access-$hour.log
  • 7. Hadoop
    • 2008/5 頃 調査
      • Hadoop Streaming
    • 2008/8 頃 稼働
      • Perl による Mapper, Reducer
      • YAML でジョブを定義
    • 2009/4 WebUI を作成
    • 2009/11 Scala 化 ← イマココ
  • 8. Hadoop Streaming
    • Java 以外の言語で MapReduce を可能に !
      • Map, Reduce の入出力を標準入力 / 標準出力として扱う -> map.pl, reduce.pl を用意するだけ
    • 通常は入力出力共に HDFS 上に置かれる
  • 9. map.pl #!/usr/bin/env perl use strict; use warnings; while (<>) { chomp; my @segments = split /s+/; printf &quot;%s %s &quot;, $segments[8], 1; }
  • 10. reduce.pl #!/usr/bin/env perl use strict; use warnings; my %count; while (<>) { chomp; my ($key, $value) = split / /; $count{$key}++; } while (my ($key, $value) = each %count) { printf &quot;%s %s &quot;, $key, $value; }
  • 11. 実行 % hadoop jar $HADOOP_DIR/contrib/hadoop-*-streaming.jar -input httpd_logs -output analog_out -mapper /home/user/work/analog/map.pl -reducer /home/user/work/analog/reduce.pl
  • 12. ジョブの定義
    • YAML で定義
    - name: latency mapper: class: LogAnalyzer::Mapper options: filters: isbot: 0 conditions: - key: Top filters: uri: '^/$' value: $response reducer: class: Reducer::Distribution input: class: LogAnalyzer::Input options: service: ugomemo period: 1 output: class: Output::Gnuplot options: title: &quot;Ugomemo Latency $date&quot; xlabel: &quot;Response time (msec)&quot; ylabel: &quot;Rates of requests (%)&quot; fotolife_folder: ugomemo
  • 13. WebUI
  • 14. Hadoop Streaming の限界
    • 遅い ← Perl の問題も ..
    • ジョブを KILL しても、プロセスが残ることがある
    • HDFS 操作が遅い
    • Combiner が定義できない
  • 15. Scala
    • 2003 年登場
    • 関数型の特徴を備えた言語
    • 普通のオブジェクト指向っぽくも書ける
    • JavaVM 上で動作する
    object HelloWorld { def main(args: Array[String]) { println(&quot;Hello, world!&quot;) } }
  • 16. Scala による Quick sort def qsort[T <% Ordered[T]](list: List[T]): List[T] = list match { case Nil => Nil case pivot::tail => qsort(tail.filter(_ < pivot)) ::: pivot :: qsort(tail.filter(_ >= pivot)) } scala> qsort(List(2,1,3)) res1: List[Int] = List(1, 2, 3)
  • 17. WordCount by Java public class WordCount { public static class Map extends MapReduceBase implements Mapper<LongWritable, IntWritable> { private final static IntWritable one = new IntWritable(1); private Text word = new Text(); public void map(LongWritable key, Text value, OutputCollector<Text, IntWritable> output, Reporter reporter) throws IOException { String line = value.toString(); StringTokenizer tokenizer = new StringTokenizer(line); while (tokenizer.hasMoreTokens()) { word.set(tokenizer.nextToken()); output.collect(word, one); } } } public static class Reduce extends MapReduceBase implements Reducer<Text, IntWritable> { …
  • 18. WordCount by Scala object WordCount { class MyMap extends Mapper[LongWritable, Text, Text, IntWritable] { val one = 1 override def map(ky: LongWritable, value: Text, output: Mapper[LongWritable, Text, Text, IntWritable]#Context) = { (value split &quot; &quot;) foreach (output write (_, one)) } } class MyReduce extends Reducer[Text, IntWritable, Text, IntWritable] { override def reduce(key: Text, values: java.lang.Iterable[IntWritable], output: Reducer[Text, IntWritable, Text, IntWritable]#Context) = { val iter: Iterator[IntWritable] = values.iterator() val sum = iter reduceLeft ((a: Int, b: Int) => a + b) output write (key, sum) } } def main(args: Array[String]) = { …
  • 19. Java vs Scala
    • Java
    • Scala
    public void map(LongWritable key, Text value, OutputCollector<Text, IntWritable> output, Reporter reporter) throws IOException { String line = value.toString(); StringTokenizer tokenizer = new StringTokenizer(line); while (tokenizer.hasMoreTokens()) { word.set(tokenizer.nextToken()); output.collect(word, one); } } override def map(ky: LongWritable, value: Text, output: Mapper[LongWritable, Text, Text, IntWritable]#Context) = { (value split &quot; &quot;) foreach (output write (_, one)) }
  • 20. Scala on Hadoop
    • Java と Scala を接続するライブラリが必要
    • SHadoop
      • http://code.google.com/p/jweslley/source/browse/#svn/trunk/scala/shadoop
      • 型変換を行うシンプルなライブラリ
  • 21. mapper class MyMap extends Mapper[LongWritable, Text, Text, IntWritable] { val one = 1 override def map(ky: LongWritable, value: Text, output: Mapper[LongWritable, Text, Text, IntWritable]#Context) = { (value split &quot; &quot;) foreach (output write (_, one)) } }
  • 22. reducer class MyReduce extends Reducer[Text, IntWritable, Text, IntWritable] { override def reduce(key: Text, values: java.lang.Iterable[IntWritable], output: Reducer[Text, IntWritable, Text, IntWritable]#Context) = { val iter: Iterator[IntWritable] = values.iterator() val sum = iter reduceLeft ((a: Int, b: Int) => a + b) output write (key, sum) } }
  • 23. main def main(args: Array[String]) = { val conf = new Configuration() val otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs() val job = new Job(conf, &quot;word count&quot;) job setJarByClass(WordCount getClass()) job setMapperClass(classOf[WordCount.MyMap]) job setCombinerClass(classOf[WordCount.MyReduce]) job setReducerClass(classOf[WordCount.MyReduce]) job setMapOutputKeyClass(classOf[Text]) job setMapOutputValueClass(classOf[IntWritable]) job setOutputKeyClass(classOf[Text]) job setOutputValueClass(classOf[IntWritable]) FileInputFormat addInputPath(job, new Path(otherArgs(0))) FileOutputFormat setOutputPath(job, new Path(otherArgs(1))) System exit(job waitForCompletion(true) match { case true => 0 case false => 1}) }
  • 24. HDFS 操作 import java.net.URI import org.apache.hadoop.fs._ import org.apache.hadoop.hdfs._ import org.apache.hadoop.conf.Configuration object Hdfs { def main(args: Array[String]) = { val conf = new Configuration() val uri = new URI(&quot;hdfs://hadoop01:9000/&quot;) val fs = new DistributedFileSystem fs.initialize(uri, conf) var status = fs.getFileStatus(new Path(args(0))) println(status.getModificationTime) } }
  • 25. ビルド手法
    • Maven
      • http://maven.apache.org/
      • Java 系のプロジェクト管理ツール
    • プロジェクト作成
    mvn org.apache.maven.plugins:maven-archetype-plugin:2.0-alpha-4:create -DarchetypeGroupId=org.scala-tools.archetypes -DarchetypeArtifactId=scala-archetype-simple -DarchetypeVersion=1.2 -DremoteRepositories=http://scala-tools.org/repo-releases -DgroupId=com.hatena.hadoop -DartifactId=hadoop
  • 26. 依存関係の記述
    • Hadoop 関連 jar の登録
    • 依存関係の記述
    <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.0.4</version> <scope>provided</scope> </dependency> <dependency> <groupId>commons-cli</groupId> <artifactId>commons-cli</artifactId> <version>1.0</version> <scope>provided</scope> </dependency> mvn install:install-file -DgroupId=org.apache.hadoop -DartifactId=hadoop-core -Dversion=0.20.1 -Dpackaging=jar -Dfile=/opt/hadoop/hadoop-0.20.1-core.jar
  • 27. ビルド・パッケージ作成と実行
    • ビルド・パッケージ作成
    • 実行
    $HADOOP_HOME/bin/hadoop jar ../maven/hadoop/target/hadoop-1.0-SNAPSHOT.jar com.hatena.hadoop.Hadoop -D mapred.job.tracker=local -D fs.default.name=file:/// input output mvn scala:compile mvn package mvn clean
  • 28. レスポンス時間の計測 #1
    • 計測方法
      • 特定の URL を叩いて、その時間を計測
      • 生アクセスログから収集
    • 生アクセスログを分析
      • Hadoop クラスタ
        • Core2Quad サーバ 10 台
        • はてなダイアリーのログ 7GB -> 10 分程度で処理
      • 分布をグラフ化
  • 29. レスポンス時間の計測 #2 Mapper URL などの条件でフィルタ レスポンス時間を記録 Reducer レスポンス時間の分布を計算 後処理 グラフ化 (gnuplot) Fotolife にアップロード (AtomAPI)
  • 30. レスポンス時間の分布グラフ
  • 31. 良好なレスポンスの例
  • 32. キャッシュによる影響
  • 33. まとめ
    • はてなでの Hadoop
    • Scala on Hadoop
    • 色々、触って楽しみましょう !
  • 34.
    • Q & A
    • [email_address]