Данила, BigData Tool Master,
собрал Hadoop - кластер,
Запустил Dataset
Он скрипты на Scala
Run'ил на Spark постоянно
И писал в HDFSssss
Если во время доклада "Когда все данные станут большими..." мы будем говорить о вопросах и ответах, то на этом мастер-классе мы уже потопчемся в вотчине BigData-разработчиков.
Начнем с классики на Hadoop, познаем боль MapReduce job, потыкаем Pig + Hive, затем плавно свальсируем в сторону Spark и попишем код в легком и удобном pipeline - стиле.
Для кого хорошо подходит данный мастер-класс: вы умеете читать и понимать код на Java на уровне хотя бы Junior, умеете писать SQL-запросы, в универе вы ходили хоть на одну пару по матану или терверу, вас либо недавно поставили, либо вскоре поставят на проект, где надо уметь ручками работать с вышеперечисленным зверинцем. Ну или вам просто интересно посмотреть на мощь даннодробилок, написанных на Java, и у вас в анамнезе неудачный опыт с NoSQL/SQL, как хранилищем, которое было ответственно за все, включая аналитику.
8. Типичный BigData кластер
• 450 машин
• Master Nodes (24 ядра, 158 Gb RAM).
• Data Nodes (24|32 ядра, 96|128 Gb RAM).
• Средняя YARN Queue utilization 85% (по
дням).
• 12Pb – емкость хранения данных
9. Когда мы говорим, что имеем дело с
BigData решением
• Когда перед глазами смесь архитектурных
подходов, таких как Kappa, Lambda, Data Lake
• Когда мы имеем дело со стеком технологий,
таких как Hadoop, Kafka, Spark, Storm, Samza,
HBase, Cassandra, Titan, GridGain
• Когда анализ логов этих систем – задача не
менее серьезного уровня
15. Если вы слишком увлечётесь гонкой
инструментов, то получится..
16. Типичный многосервисный проект,
где основной болью будет конфликт
разных версий
Real-Time Data-Marts
Batch Data-Marts
Relations Graph
Ontology Metadata
Search Index
Events & Alarms
Real-time
Dashboarding
Events & Alarms
All Raw Data backup
is stored here
Real-time Data
Ingestion
Batch Data
Ingestion
Real-Time ETL & CEP
Batch ETL & Raw Area
Scheduler
Internal
External
Social
HDFS → CFS
as an option
Time-Series Data
Titan & KairosDB
store data in Cassandra
Push Events & Alarms (Email, SNMP etc.)
20. Пора дать определение!
• Hadoop != MapReduce
• Hadoop – это фреймворк
• Фреймворк для обработки больших
массивов данных
21. Пора дать определение!
• Hadoop != MapReduce
• Hadoop – это фреймворк
• Фреймворк для обработки больших
массивов данных
• Который использует простые модели и
парадигмы программирования
22. Пора дать определение!
• Hadoop != MapReduce
• Hadoop – это фреймворк
• Фреймворк для обработки больших
массивов данных
• Который использует простые модели и
парадигмы программирования
• Скрывая от нас всю самую сложную часть с
параллелизацией, перемещением данных и
38. Нравится много писать в консоли?
Big Data on your local machine : How to install Hadoop 2.6.0
39. Режим установки local
• Однопоточная Java
• Легко дебажить даже из IDE
• Репликации нет
• HDFS учить не нужно
• dfs.replication=“1”;
• fs.defaultFS=“file:///”;
fs.default.name=“file:///”;
• mapreduce.framework.name=“local”
40. Режим установки Pseudo-distributed
• Все на одной ноде
• Репликации нет
• Каждому демону из Hadoop соответсвует
thread из Java
• Yarn выполняет свою работу
43. Best Practices
• DataNodes, NodeManagers and RegionServers
обычно разворачиваются исходя из
стратегии DataLocality
44. Best Practices
• DataNodes, NodeManagers and RegionServers
обычно разворачиваются исходя из
стратегии DataLocality
• Обычно каждый блок данных реплицируется
минимум трижды в действительно разных
местах
45. Best Practices
• DataNodes, NodeManagers and RegionServers
обычно разворачиваются исходя из
стратегии DataLocality
• Обычно каждый блок данных реплицируется
минимум трижды в действительно разных
местах
• Если можно, ставим балансировщик
46. Best Practices
• DataNodes, NodeManagers and RegionServers
обычно разворачиваются исходя из
стратегии DataLocality
• Обычно каждый блок данных реплицируется
минимум трижды в действительно разных
местах
• Если можно, ставим балансировщик
• Изучаем особенности HDFS
47. Рекомендации по мощностям
• 64GB RAM для NameNode позволяют
адресоваться ~100M files в HDFS
• 256 GB RAM для data nodes и интенсивными
in-memory operations (например Spark
executors, или in-memory DBs)
• Минимум 8-16 cores CPUs
• Минимум 4 дисков (для master nodes) и 6-12
дисков (для data nodes) для IO optimization; +
1 отдельный диск для OS
49. Hadoop Distributed File System
Hortonworks утверждает, что
существуют кластера на 200 PB, 4500
машин, > 10^6 файлов и HDFS
нормально так работает
50. NameNode
• Вообще это отдельные процессы, которые
умеют жить как на одной, так и на разных
машинах
• В кластере только одна NameNode, но это не
SPOF!
• Есть StanbyNameNode, она страхует
• Если NameNode недоступна, то недоступен и
HDFS кластер
52. DataNode
• DataNode может быть сколько угодно, чем
больше, тем лучше
• Можно убирать и добавлять их без особого
ущерба
• DataNode сама отвечает на запросы
• И слушается NameNode, когда надо умереть,
реплицировать что-то или удалить реплику
53. Что нужно уметь и знать!
• Перемещать данные между HDFS и обычной
FS: hdfs fs -copyFromLocal ; -copyToLocal
• Удалять/создавать директории
• Управлять правами на файлы/папки
• Диагностировать
• Проверять наличие свободного пространства
Все это при помощи команд, похожих на Linux
63. Как запустить это хозяйство?
• Сделать jar
• Запустить его на удаленной машине, где есть Hadoop
64. Как запустить это хозяйство?
• Сделать jar
• Запустить его на удаленной машине, где есть Hadoop
• hadoop jar your-jar.jar <packagename>.YourDriver –
Ddir.input=/bla/bla/bla -Dmapred.reduce.tasks=4
65. Как запустить это хозяйство?
• Сделать jar
• Запустить его на удаленной машине, где есть Hadoop
• hadoop jar your-jar.jar <packagename>.YourDriver –
Ddir.input=/bla/bla/bla -Dmapred.reduce.tasks=4
• В коде драйвера работай с этими константами
66. Как запустить это хозяйство?
• Сделать jar
• Запустить его на удаленной машине, где есть Hadoop
• hadoop jar your-jar.jar <packagename>.YourDriver –
Ddir.input=/bla/bla/bla -Dmapred.reduce.tasks=4
• В коде драйвера работай с этими константами
• String hdfsInputFileOrDirectory =
configuration.get(“dir.input”);
82. Сделаем отчет на Pig
dem = LOAD '/ok/demography/part-r-00000' AS (id:int, age:int,
gender:int, region:int);
83. Сделаем отчет на Pig
dem = LOAD '/ok/demography/part-r-00000' AS (id:int, age:int,
gender:int, region:int);
logins = LOAD '/ok/logins/*' AS (ts:chararray, userid:int, clientType:int,
success:boolean, geoIp:int, userAgent:int);
84. Сделаем отчет на Pig
dem = LOAD '/ok/demography/part-r-00000' AS (id:int, age:int,
gender:int, region:int);
logins = LOAD '/ok/logins/*' AS (ts:chararray, userid:int, clientType:int,
success:boolean, geoIp:int, userAgent:int);
by_user_success = GROUP logins BY (userid, success);
85. Сделаем отчет на Pig
dem = LOAD '/ok/demography/part-r-00000' AS (id:int, age:int,
gender:int, region:int);
logins = LOAD '/ok/logins/*' AS (ts:chararray, userid:int, clientType:int,
success:boolean, geoIp:int, userAgent:int);
by_user_success = GROUP logins BY (userid, success);
logins_data = FOREACH by_user_success
GENERATE FLATTEN (group) as (userid, success),
COUNT(logins.ts) as login_amount;
86. Сделаем отчет на Pig
dem = LOAD '/ok/demography/part-r-00000' AS (id:int, age:int,
gender:int, region:int);
logins = LOAD '/ok/logins/*' AS (ts:chararray, userid:int, clientType:int,
success:boolean, geoIp:int, userAgent:int);
by_user_success = GROUP logins BY (userid, success);
logins_data = FOREACH by_user_success
GENERATE FLATTEN (group) as (userid, success),
COUNT(logins.ts) as login_amount;
DESCRIBE logins_data;
87. Сделаем отчет на Pig
/* amount of logins by regions */
dem_logins= JOIN dem BY id, logins_data BY userid;
88. Сделаем отчет на Pig
/* amount of logins by regions */
dem_logins= JOIN dem BY id, logins_data BY userid;
by_region = GROUP dem_logins BY (region, gender, success);
89. Сделаем отчет на Pig
/* amount of logins by regions */
dem_logins= JOIN dem BY id, logins_data BY userid;
by_region = GROUP dem_logins BY (region, gender, success);
result = FOREACH by_region
GENERATE FLATTEN (group) as (region, gender, success),
SUM(dem_logins.login_amount) as login_amount;
90. Сделаем отчет на Pig
/* amount of logins by regions */
dem_logins= JOIN dem BY id, logins_data BY userid;
by_region = GROUP dem_logins BY (region, gender, success);
result = FOREACH by_region
GENERATE FLATTEN (group) as (region, gender, success),
SUM(dem_logins.login_amount) as login_amount;
DESCRIBE result;
91. Сделаем отчет на Pig
/* amount of logins by regions */
dem_logins= JOIN dem BY id, logins_data BY userid;
by_region = GROUP dem_logins BY (region, gender, success);
result = FOREACH by_region
GENERATE FLATTEN (group) as (region, gender, success),
SUM(dem_logins.login_amount) as login_amount;
DESCRIBE result;
STORE result INTO '/ok/dem_logins_by_region' using PigStorage(',');
92. Да по-любому надо тюнить!
set default_parallel 64;
set job.name Calculate_number_of_users;
set mapred.child.java.opts -Xmx1024m
dem = LOAD '/ok/demography/part-r-00000' AS (id:int, age:int,
gender:int, region:int);
….
94. Как так? Снова SQL?
Да, дружище, он никуда не уходил, стоял за дверью…
95. Причины триумфа Hive
• Иллюзия структуры
• Единый язык для различных хранилищ
• SQL всем знаком
• Вполне реален ответ за небольшое время
• MapReduce слишком сложен
• Иллюзия JOINs
101. Почему мамонты вымирают?
• Они слишком часто сохраняются на диск
• Слишком много людей сидят на абстракциях,
а не пишут MR jobs
102. Почему мамонты вымирают?
• Они слишком часто сохраняются на диск
• Слишком много людей сидят на абстракциях,
а не пишут MR jobs
• Слишком плох MR для итерационных
вычислений
103. Почему мамонты вымирают?
• Они слишком часто сохраняются на диск
• Слишком много людей сидят на абстракциях,
а не пишут MR jobs
• Слишком плох MR для итерационных
вычислений
• Слишком долго MR был на коне
104. Почему мамонты вымирают?
• Они слишком часто сохраняются на диск
• Слишком много людей сидят на абстракциях,
а не пишут MR jobs
• Слишком плох MR для итерационных
вычислений
• Слишком долго MR был на коне
• И да, Google его больше не использует
105. Мы можем комбинировать подходы
для всех источников данных
val points = spark.sql("select latitude, longitude
from tweets")
val model = KMeans.train(points, 10)
106. WordCount на Scala + Spark
val conf = new SparkConf()
.setAppName(appName)
.setMaster(master)
107. WordCount на Scala + Spark
val conf = new SparkConf()
.setAppName(appName)
.setMaster(master)
val spark = new SparkContext(conf)
108. WordCount на Scala + Spark
val conf = new SparkConf()
.setAppName(appName)
.setMaster(master)
val spark = new SparkContext(conf)
val file = spark.textFile("…")
res.saveAsTextFile("…");
109. WordCount на Scala + Spark
val conf = new SparkConf()
.setAppName(appName)
.setMaster(master)
val spark = new SparkContext(conf)
val file = spark.textFile("…")
Тут как напишем сейчас MR!
res.saveAsTextFile("…");
110. WordCount на Scala + Spark
val conf = new SparkConf()
.setAppName(appName)
.setMaster(master)
val spark = new SparkContext(conf)
val file = spark.textFile("…")
val res = file
.flatMap(line => line.split(" "))
.map(word => (word, 1))
.reduceByKey(_+_)
res.saveAsTextFile("…");