spark: нетипичные примеры использования
TRANSCRIPT
Spark: нетипичные примеры
использования
О чём пойдёт речь
● что можно выжать из Spark● с чем могут быть проблемы● ничего сверхъестественного● это есть в документации (но кто читает дальше первой страницы?)
DISCLAIMER
Теперь не верьте моим словам только потому, что их сказал Будда, но проверяйте
их как следует
Будда Шакьямуни
Типичный пример
rdd.map(processor) .reduce(reducer)
rdd = sc.textFile(“hdfs://...”)
stream = KafkaUtils.createStream(...)
rdd.saveAsTextFile(...)
Обращение ко внешним сервисам
data enrichment
Обращение ко внешним сервисам (2)
data enrichment
dstream.foreachRDD { rdd =>
// executed at the driver val connection = createNewConnection() rdd.foreach { record =>
// executed at the worker connection.send(record) }}
Важно: соединения не сереализуемыНЕПРАВИЛЬНО!
dstream.foreachRDD { rdd =>
// executed at the driver val connection = createNewConnection() rdd.foreach { record =>
// executed at the worker connection.send(record) }}
Важно: соединения не сереализуемыНЕПРАВИЛЬНО!
dstream.foreachRDD { rdd => rdd.foreach { record => val connection = createNewConnection() connection.send(record) connection.close() }}
НЕЭФФЕКТИВНО!
dstream.foreachRDD { rdd => rdd.foreachPartition { partitionOfRecords =>
// connection per partition, i.e. per worker machine val connection = createNewConnection() partitionOfRecords.foreach(record => connection.send(record)) connection.close() }}
Правильный вариант
Worker Worker Worker
connectio
n connection
conn
ectio
n
Процессы без входных данных
worker worker worker worker
Driver
Процессы без входных данных (2)
def runSimulation(workerId: Int): Unit = {
...
}
sc.parallelize(1 to NWorkers, NWorkers)
.map(runSimulation)
.collect()
numSlices - количество партиций
Обратная связь
worker worker worker worker
Driver BadFormatException
Обратная связь (2)
worker worker worker worker
Driver RabbitMQ
BadFormatException
Обратная связь (Ninja level)
worker worker worker worker
Driver Akka
SparkContext.env.actorSystem
BadFormatException
Одновременные джобыЧто будет, если…
(1) val sourceRdd = sc.textFile(...)
(2) sourceRdd.filter(x => x == 42).map(...).collect()
(3) sourceRdd.filter(x => x != 42).map(...).collect()
(2) и (3) выполнятся параллельно или последовательно?
Одновременные джобы (2)Что будет, если…
(1) val sourceRdd = sc.textFile(...)
(2) sourceRdd.filter(x => x == 42).map(...).collect()
(3) sourceRdd.filter(x => x != 42).map(...).collect()
(2) и (3) выполнятся параллельно или последовательно?Блокер - сам драйвер
Одновременные джобы (3)
(1) val sourceRdd = sc.textFile(...)
(2) val rdd1 = sourceRdd.filter(x => x == 42).map(...)
(3) val rdd2 = sourceRdd.filter(x => x != 42).map(...)
(4) List(rdd1, rdd2).par.foreach { rdd =>
rdd.collect()
}
Пример: SQL-сервер
Server(Driver)
Query (Job)
Query (Job)
Query (Job)val conf = new SparkConf()
// conf.set("spark.scheduler.mode",
"FIFO")
conf.set("spark.scheduler.mode", "FAIR")
val sc = new SparkContext(conf)
Перебалансировка партициймного файлов = много партиций
rdd.coalesce(4)
Перебалансировка партиций (2)gzip - неделимый формат
rdd.repartition(10)
split ‘em, Shura, they are golden!
Сэмплирование данныхval rdd = sc.parallelize(1 to 1000)
// takeSample(withReplacement, num)
rdd.takeSample(false, 10) // ⇒ array of 10 elements, but calls .count()
// sample(withReplacement, fraction)
rdd.sample(false, 0.01).collect() // ⇒ array of 7 elements
rdd.sample(false, 0.01).collect() // ⇒ array of 14 elements
rdd.sample(false, 0.01).collect() // ⇒ array of 13 elements
Thank you!