Projet Calypso
Présentation
Purch
- Online marketing business
- À Grenoble : anciennement Best of Media
- Responsables de :
- Tom's Guide / IT / Hardware
- TopTenReviews
- Space.com
- ...
Projet Calypso
- Moteur de recommandation
- Publicités
- Basé sur le comportements des autres utilisateurs
- Plusieurs centaines de millions d'actions à traiter par jour
L'équipe
- Projet conjoint entre :
- Purch
- Kelkoo
- LIG
- Parties communes / spécifiques
Quelles informations ?
- Plates-formes de publicités
- Tracking de clicks
Quelles contraintes ?
- BLAZIN' FAST
- < 200ms
- Beaucoup de données
- Suivi "temps réel" des tendances
Technologies
- Kafka
- Spark
- HDFS
- Scala
Scala
Un tour rapide
Introduction
- Langage de programmation multi-paradigme
- Conçu à l'EPFL
- Compilable en bytecode JAVA
- Profite des librairies JAVA
Pourquoi Scala ?
- Langage natif de Spark
- Fonctionnel
Principaux apports de Scala
- Fonctions lambda
- Currying
- Extracteurs
- Inférence de type
- Syntaxe très sucrée
- ...
foo.bar("toto");
def add(x: Int, y: Int): Int = {
return x + y;
}
List(1, 2, 3, 4).map(x => {
return add(x, 5);
});
Le sucre syntaxique
foo.bar("toto");
def add(x: Int, y: Int): Int = {
return x + y;
}
List(1, 2, 3, 4).map(x => {
return add(x, 5);
});
Le sucre syntaxique
foo bar "toto"
def add(x: Int, y: Int): Int = x + y
(1 to 4).map { add(_, 5) }
def process[A](filter:A=>Boolean)(list:List[A]):List[A] = {
lazy val recurse = process(filter) _
list match {
case head::tail => if (filter(head)) {
head::recurse(tail)
} else {
recurse(tail)
}
case Nil => Nil
}
}
val even = (a:Int) => a % 2 == 0
val numbersAsc = 1::2::3::4::5::Nil
val numbersDesc = 5::4::3::2::1::Nil
process(even)(numbersAsc) // [2, 4]
process(even)(numbersDesc) // [4, 2]
Un exemple assez ouf
L'underscore en Scala
Ou : "What the actual fuck"
// Imports all the classes in the package matching
import scala.util.matching._
// Imports all the members of the object Fun (static import in Java).
import com.test.Fun._
// Imports all the members of the object Fun but renames Foo to Bar
import com.test.Fun.{ Foo => Bar , _ }
// Imports all the members except Foo. To exclude a member rename it to _
import com.test.Fun.{ Foo => _ , _ }
The Underscore: part 1
def matchTest(x: Int): String = x match {
case 1 => "one"
case 2 => "two"
case _ => "anything other than one and two"
}
expr match {
case List(1,_,_) => " a list with three element and the first element is 1"
case List(_*) => " a list with zero or more elements "
case Map[_,_] => " matches a map with any key type and any value type "
case _ =>
}
List(1,2,3,4,5).foreach( a => print(a))
// Same as:
List(1,2,3,4,5).foreach(print(_))
List((1,2), (3,4)).foreach( (a, b) => print(a + b))
// Same as:
List((1,2), (3,4)).foreach(print(_ + _))
The Underscore strikes back
def f() = { println("Yo dawg.") ; 42 }
def g(): Unit = { f() }
// warning: discarded non-Unit value
// def g(): Unit = { f() }
// ^
def g(): Unit = { val _ = f() }
// scala> g
// Yo dawg.
The Underscore 3: in space
Les extracteurs
case class User(
firstName: String,
lastName: String,
score: Int
)
val user = new User("Maxime", "Vacher", 2)
user match {
case User(firstName, lastName, score) => println(s"Hello, $firstName !")
case _ =>
}
def advance(xs: List[User]) = xs match {
case User(_, _, score1) :: User(_, _, score2) :: _ => score1 - score2
case _ => 0
}
Les extracteurs, juge et flic
trait User {
def name: String
}
class FreeUser(val name: String) extends User
class PremiumUser(val name: String) extends User
object FreeUser {
def unapply(user: FreeUser): Option[String] = Some(user.name)
}
object PremiumUser {
def unapply(user: PremiumUser): Option[String] = Some(user.name)
}
val user: User = new PremiumUser("Daniel")
user match {
case FreeUser(name) => "Hello " + name
case PremiumUser(name) => "Welcome back, dear " + name
}
Les extracteurs contre César
object Twice {
def apply(x: Int): Int = x * 2
def unapply(z: Int): Option[Int] = if (z%2 == 0) Some(z/2) else None
}
object TwiceTest extends App {
val x = Twice(21)
x match {
case Twice(n) => Console.println(n) // prints 21
}
}
Les extracteurs et les gendarmettes
Implicit
Et après on arrête avec Scala
def add(a: Int, b: Int): Int = a + b
> add("maxime", "vacher") // Won't compile
Les convertisseurs implicites
implicit toInt(string: String): Int = string.length
> add("maxime", "vacher") // 12
class Prefixer(val prefix: String)
def addPrefix(s: String)(implicit p: Prefixer) = p.prefix + s
Les paramètres implicites
implicit val myImplicitPrefixer = new Prefixer("<3 ")
addPrefix("Maxime Vacher") // <3 Maxime Vacher
Traitement Big Data
C'est bientôt fini
Kafka
- Système distribué de messagerie
- Flux de données en temps réel
Spark
- Framework de calcul distribué
- Travaille sur la RAM
- Abstraction (partielle) pour le développeur
- Notion de RDD
Winter is coming
HDFS
- Système de fichier du framework Hadoop
- Distribué
- Tolérant à la panne
Merci de votre sage attention
Présentation Purch
By Marc Schaller
Présentation Purch
- 390