読者です 読者をやめる 読者になる 読者になる

Spring Boot の練習

Java

https://github.com/qwerqwer1111/spring-boot-todo

練習がてら Todo アプリケーションを作った. 使った道具は下記のような感じ.

  • Spring Boot
  • DynamoDB (実際には DynamoDB Local)
  • Vue.js

Java のパッケージ構成は TERASOLUNA のガイドラインを参考にした.

Vue.js は前から気になっていたので使ってみたけど, Thymeleaf とはちょっと相性が悪いかも知れない (というか, 使いどころを間違えた気がする……).

『初めてのSpark』を読み始めた (5)

Scala Spark

アクション

アクションの例.

データの全体, 一部をドライバプログラムに返すもの

  • collect(): RDD の内容全体を通常のコレクションとしてドライバに返す
  • count(): RDD の要素数を返す
  • countByValue(): RDD の各要素の要素数を返す
  • take(num): RDD の先頭から num 個の要素を返す
  • top(num): 値の大きい方から num 個の要素を返す
  • takeOrdered(num): 値の小さい方から num 個の要素を返す
  • takeSample(withReplacement, num): num 個の要素をランダムに返す
    • withReplacementtrue を指定すると, 同じ要素が何度も返却されることがある
$ spark-shell
...
scala> val input = sc.parallelize(List(1, 2, 3, 3))
scala> val collectResult = input.collect()
scala> println(collectResult.getClass.getSimpleName)
int[]
scala> println(collectResult.mkString(", "))
1, 2, 3, 3
scala> val countResult = input.count()
scala> println(countResult.getClass.getSimpleName)
long
scala> println(countResult)
4

scala> val countByValueResult = input.countByValue()
scala> println(countByValueResult.getClass.getSimpleName)
Map3
scala> println(countByValueResult.mkString(", "))
1 -> 1, 2 -> 1, 3 -> 2

scala> val takeResult = input.take(2)
scala> println(takeResult.getClass.getSimpleName)
int[]
scala> println(takeResult.mkString(", "))
1, 2

scala> val topResult = input.top(2)
scala> println(topResult.getClass.getSimpleName)
int[]
scala> println(topResult.mkString(", "))
3, 3

scala> val takeOrderedResult = input.takeOrdered(2)
scala> println(takeOrderedResult.getClass.getSimpleName)
int[]
scala> println(takeOrderedResult.mkString(", "))
1, 2

scala> val takeSampleResult = input.takeSample(false, 2)
scala> println(takeSampleResult.getClass.getSimpleName)
int[]
scala> println(takeSampleResult.mkString(", "))
3, 3

『初めてのSpark』を読み始めた (4)

Scala Spark

変換の例.

基本的な変換

  • map(): 関数を RDD の各要素に適用した新しい RDD を返す
  • filter(): 関数が真になる要素のみを含む RDD を返す
  • distinct(): 重複する要素を取り除く. ネットワーク上ですべてのデータをシャッフルするため, コストのかかる処理であることに注意する
  • flatMap(): 関数を RDD の各要素に適用し, 結果のイテレータ群から成る新しい RDD を返す
$ spark-shell
...
scala> val input = sc.parallelize(List(1, 2, 3, 3, 4, 4))
scala> val mapResult = input.map(x => x * x)
scala> println(mapResult.collect().mkString(", "))
1, 4, 9, 9, 16, 16

scala> val filterResult = input.filter(x => x > 3)
scala> println(filterResult.collect().mkString(", "))
4, 4

scala> val distinctResult = input.distinct()
scala> println(distinctResult.collect().mkString(", "))
4, 1, 2, 3

scala> val lines = sc.parallelize(List("hoge hoge", "fuga", "fuga piyo"))
scala> val flatMapResult = lines.flatMap(line => line.split(" "))
scala> println(flatMapResult.collect().mkString(", "))
hoge, hoge, fuga, fuga, piyo

集合操作(2016/04/16 追記)

  • union(other): それぞれの RDD に含まれる要素からなる RDD を返却する
    • 重複する要素はそのまま含まれる
  • intersection(other): 双方の RDD に含まれる要素からなる RDD を返却する
    • 重複する要素はすべて取り除かれる(片方の RDD 内の重複する要素も取り除かれることに注意する)
    • ネットワーク経由でシャッフルがおこなわれる
  • subtract(other): ソース RDD から other に含まれる要素を取り除く
    • シャッフルがおこなわれる
  • cartesian(other): 双方の RDD の直積を返却する
    • 大規模な RDD に対して実行することは, きわめて大きいコストがかかることに注意する
$ spark-shell
...
scala> val input = sc.parallelize(List(1, 2, 3))
scala> val other = sc.parallelize(List(3, 4, 5))

scala> val unionResult = input.union(other)
scala> println(unionResult.collect().mkString(", "))
1, 2, 3, 3, 4, 5

scala> val intersectionResult = input.intersection(other)
scala> println(intersectionResult.collect().mkString(", "))
3

scala> val subtractResult = input.subtract(other)
scala> println(subtractResult.collect().mkString(", "))
1, 2

scala> val cartesianResult = input.cartesian(other)
scala> println(cartesianResult.collect().mkString(", "))
(1,3), (1,4), (1,5), (2,3), (2,4), (2,5), (3,3), (3,4), (3,5)

『初めてのSpark』を読み始めた (3)

Scala Spark

RDD(Resilient Distributed Dataset)について.

RDD(Resilient Distributed Dataset)

  • イミュータブルな分散された要素のコレクション
  • 複数パーティションに分割されていて, それぞれに対する演算処理がクラスタの各ノード上で行われる
  • 下記の 2 種類の方法で生成できる
    1. 外部のデータセットをロードする
    2. オブジェクトのコレクションをドライバプログラムから配分する
  • RDD には, 変換とアクションの 2 種類の操作が行える

変換

ある RDD から新しい RDD を構築する. 例えば, filter() など. 変換の操作は既存の RDD を変化させるのではなく, 新しい RDD へのポインタを返す.

$ spark-shell
...
scala> val lines = sc.textFile("/usr/local/Cellar/apache-spark/1.6.1/README.md")
...
scala> val scalaLines = lines.filter(line => line.contains("Scala"))
...

アクション

RDD をもとに結果を計算したり, その結果をドライバプログラムに戻したり, 外部のストレージシステムに保存したりする. 例えば, first() など.

scala> scalaLines.first()
res1: String = high-level APIs in Scala, Java, Python, and R, and an optimized engine that
  • 定義された RDD は, 初めてアクションが使われた時点でその生成処理が行われる
  • RDD は, それに対するアクションが実行されるたびに計算し直される
    • ある RDD を何度もアクションで再利用するのであれば, RDD.persist() で永続化できる

iTerm2 の設定メモ

Mac

Terminal から iTerm2 に移行したので, 設定のメモ.

インストール

$ brew cask install iterm2

カラースキームの設定

Solarized Dark に設定した.

  1. Solarized の GitHub リポジトリから iterm2-colors-solarized/Solarized Dark.itermcolors をダウンロード
  2. Preferences... > Profiles > 左下の + から新しいプロファイルを作成して, 適当な名前を付ける
    • Other Actions... > Set as Default でデフォルトに設定しておく
  3. Colors タブ > Load Presets... ドロップダウンから Import を選択して, Solarized Dark.itermcolorsを読み込み

もう長いこと Solarized Dark ばかり使っているので, そろそろ別のカラースキームも使ってみたい…….

その他の設定

  • Preferences...
    • General
      • SelectionCopy to clipboard on selection のチェックを外す
    • Profiles > 先ほど作成したプロファイルに対して下記を設定する.
      • General
        • Working Directory > Advanced Configuration にチェックして Edit
          • Working Directory for New Tabs > Reuse previous session's directory に変更
          • Working Directory for New Split Panes > Reuse previous session's directory に変更
      • Text
        • Cursor > Blinking cursor にチェック
        • Regular Font, Non-ASCII Font > Ricky 12pt に変更
        • Double-Width Characters > Treat ambiguous-width characters as double width にチェック
      • Window
        • Transparency を少し上げる
      • Keys
        • Left option key acts as > +Esc にチェック
        • Right option key acts as > +Esc にチェック

複数行の貼付け時に確認ウィンドウを出す

ターミナルに貼り付けたコマンドに改行があって, たまに悲しいことになるので設定. 下記のリポジトリのものを利用した.

https://github.com/harasou/may-i-paste

『初めてのSpark』を読み始めた (2)

Scala Spark

次はスタンドアローンアプリケーションの構築.

下記の GitHub リポジトリで色々練習する予定.

https://github.com/qwerqwer1111/spark-example

作業内容

SBT のビルドファイルに dependency を追加.

libraryDependencies ++= Seq(
  "org.apache.spark" %% "spark-core" % "1.6.0" % "provided"
)

実際のアプリケーションは下記のような感じ.

package com.github.qwerqwer1111.spark

import org.apache.spark.{SparkContext, SparkConf}

object WordCount {

  def main(args: Array[String]) {
    if (args.length != 2) sys.exit(-1)

    val inputFile = args(0)
    val outputFile = args(1)

    val conf = new SparkConf().setAppName("WordCount")
    val sc = new SparkContext(conf)

    val input = sc.textFile(inputFile)

    val words = input.flatMap(line => line.split(" "))
    val counts = words.map(word => (word, 1))
      .reduceByKey(_ + _)

    counts.saveAsTextFile(outputFile)
  }
}

ビルド. 実際は IntelliJ IDEA 上から実行した.

$ sbt clean package

spark-submitで実行.

$ spark-submit \
  --class com.github.qwerqwer1111.spark.WordCount \
  target/scala-2.11/spark-example_2.11-1.0.jar \
  /usr/local/Cellar/apache-spark/1.6.0/README.md \
  ./wordcounts

wordcountsディレクトリの下に_SUCCESS, part-xxxxxのようなファイルが出力された. part-xxxxxの中身は下記のような感じ.

(For,2)
(Programs,1)
(Spark,13)
(particular,2)
(The,1)
...

追記

2016/04/16 追記

Spark 1.3.0 では import org.apache.spark.SparkContext._ の明示的なインポートが必要だったが, 現在は必要ないらしい.

『初めてのSpark』を読み始めた

Scala Spark

とりあえず, ローカルの開発環境構築から.

環境

  • OS X El Capitan 10.11.3

作業内容

Mac だと, Homebrew でもインストールできた.

$ brew install apache-spark

spark-shell を動かしてみる.

$ spark-shell
...
scala> val lines = sc.textFile("/usr/local/Cellar/apache-spark/1.6.0/README.md")
lines: org.apache.spark.rdd.RDD[String] = MapPartitionsRDD[...] ...

scala> lines.count()
res0: Long = 95

scala> lines.first()
res1: String = # Apache Spark

http://localhost:4040/jobs/ で, Spark UI にもアクセスできた.