Обзор Hadoop от Google (dataproc)

в 18:51, , рубрики: big data, dataproc, Hadoop

Некоторое время назад я активировал у гугла бесплатный триал под их клауд, задачку я свою не решил, оказалось гугл дает $300 на 12 месяцев под триал, однако вопреки моим ожиданиям кроме лимита бюджета накладываются и другие лимиты. Например не позволил использовать виртуалки более 8 vcpu в одном регионе. Спустя пол года решил использовать триальный бюджет на знакомство с dataproc, предустановленный хадуп кластер от гугла. Задача — попытаться оценить на сколько просто было бы мне запустить проект на гугловом хадупе, есть ли в нем смысл или лучше сразу ориентироваться на свое железо и продумывать администрирование. Есть у меня смутное ощущение, что современное железо и бигдата стек уже легко должен адаптироваться и под небольшие базы данных в десятки или сотни Гб, брутально загружая если не весь датасет, то подавляющую часть в память кластера. Какие-то отдельные субд под витрины данных уже могут и не потребоваться.
Если в вкратце то в dataproc впечатлила простота запуска и настроек, на фоне Oracle и Cloudera. На первом этапе я играл с one node cluster на 8 vCpu, максимум какой позволяет совсем бесплатный триал. Если смотреть на простоту, то их технологии уже позволяют совсем индусу в 15 минут запустить кластер, загрузить сампл данные и подготовить отчетик обычным BI инструментом, без каких либо промежуточных субд под витрины. Каких-то глубоких знаний о хадупе уже совсем не требуется.

В принципе я увидел, что штука замечательная под быстрый старт и за вменяемые деньги можно запустить прототип, оценить какое железо под задачку понадобиться. Однако кластер покрупней, в десятки нод, явно будет кушать значительно больше, чем аренда + пара приглядывающих за кластером админа. Далеко не факт, что клауд будет выглядеть экономически выгодным. Первым этапом я попытался оценить совсем микро вариант с one node cluster 8 vCpu и 0.5 Тб сырых данных. В принципе тестов spark+hadoop на кластерах покрупней и так полно в инетах, но я планирую и чуть крупнее вариант потестировать позже.
Буквально за час я нагуглил скрипты создания хадуп кластера, настроек его firewall и настройки thrift server, который позволил по jdbc с домашней винды подключаться к spark sql. Еще часа два-три я потратил на оптимизацию дефолтных настроек spark и загрузку пары мелких таблиц размером около 10 Гб (размер датафайлов в оракле). Таблицы я запихнул целиком в память (alter table cache;) и с ними можно было работать с моей Windows машины из Dbeaver и Tableau (через spark sql коннектор).
По дефолту спарк использовал лишь 1 executor на 4 vCpu, я отредактировал spark-defaults.conf, поставил 3 executers, по 2 vCpu и долго не мог понять почему у меня реально в работе лишь 1 executer. Выяснилось что я не отредактировал память, двум другим yarn просто не мог выделить память. Я выставил 6.5 Гб на executer, после этого как ожидалось начали подниматься все три.
Далее я решил поиграть с чуть серьезней объемами и более приближенной к DWH задачей из тестов TPC-DS. Для начала я официальной тулзой сгенерировал таблицы со scale factor 500. Получилось что-то около 480 Гб сырых данных (текст с разделителем). Тест TPC-DS — типичное DWH, с фактами и дименсиями. Как сгенерировать данные сразу на google storage я не понял, пришлось генерировать на диск виртуалки и потом копировать на google storage. Гугл как я понял считает, что хадуп отлично работает с google storage и скорость там обещает чуть не лучше, чем если бы данные лежали внутри кластера на HDFS. При этом получается часть нагрузки уходит с HDFS на google storage.
Подключившись через Dbeaver я SQL командами переконвертировал текстовые файлы в таблички на базе parquet со snappy упаковкой. 480 Гб текстовых данных упаковались в 187 Гб parquet файлы. Занял процесс порядка двух часов, крупнейшая таблица занимала в тексте 188 Гб, 3 spark executers в parquet их превратили за 74 минуты, размер паркетника 66.8 Гб. На своем десктопе с примерно теми же 8 vCpu (i7-3770k) думаю «insert into table select * ...» в оракловую таблицу с 8к блоком занял бы сутки, а сколько бы занял датафайл даже страшно представить.

image

Далее я проверил работоспособность BI инструментов на таком конфиге, построил простенький отчет в Tableua

image

Что касается запросов то Query1 из теста TPC-DS

Query1

WITH customer_total_return 
     AS (SELECT sr_customer_sk     AS ctr_customer_sk, 
                sr_store_sk        AS ctr_store_sk, 
                Sum(sr_return_amt) AS ctr_total_return 
         FROM   store_returns, 
                date_dim 
         WHERE  sr_returned_date_sk = d_date_sk 
                AND d_year = 2001 
         GROUP  BY sr_customer_sk, 
                   sr_store_sk) 
SELECT c_customer_id 
FROM   customer_total_return ctr1, 
       store, 
       customer 
WHERE  ctr1.ctr_total_return > (SELECT Avg(ctr_total_return) * 1.2 
                                FROM   customer_total_return ctr2 
                                WHERE  ctr1.ctr_store_sk = ctr2.ctr_store_sk) 
       AND s_store_sk = ctr1.ctr_store_sk 
       AND s_state = 'TN' 
       AND ctr1.ctr_customer_sk = c_customer_sk 
ORDER  BY c_customer_id
LIMIT 100;

выполнился за 1:08, Query2 с участием крупнейших таблиц (catalog_sales, web_sales)

Query2

WITH wscs 
     AS (SELECT sold_date_sk, 
                sales_price 
         FROM   (SELECT ws_sold_date_sk    sold_date_sk, 
                        ws_ext_sales_price sales_price 
                 FROM   web_sales) 
         UNION ALL 
         (SELECT cs_sold_date_sk    sold_date_sk, 
                 cs_ext_sales_price sales_price 
          FROM   catalog_sales)), 
     wswscs 
     AS (SELECT d_week_seq, 
                Sum(CASE 
                      WHEN ( d_day_name = 'Sunday' ) THEN sales_price 
                      ELSE NULL 
                    END) sun_sales, 
                Sum(CASE 
                      WHEN ( d_day_name = 'Monday' ) THEN sales_price 
                      ELSE NULL 
                    END) mon_sales, 
                Sum(CASE 
                      WHEN ( d_day_name = 'Tuesday' ) THEN sales_price 
                      ELSE NULL 
                    END) tue_sales, 
                Sum(CASE 
                      WHEN ( d_day_name = 'Wednesday' ) THEN sales_price 
                      ELSE NULL 
                    END) wed_sales, 
                Sum(CASE 
                      WHEN ( d_day_name = 'Thursday' ) THEN sales_price 
                      ELSE NULL 
                    END) thu_sales, 
                Sum(CASE 
                      WHEN ( d_day_name = 'Friday' ) THEN sales_price 
                      ELSE NULL 
                    END) fri_sales, 
                Sum(CASE 
                      WHEN ( d_day_name = 'Saturday' ) THEN sales_price 
                      ELSE NULL 
                    END) sat_sales 
         FROM   wscs, 
                date_dim 
         WHERE  d_date_sk = sold_date_sk 
         GROUP  BY d_week_seq) 
SELECT d_week_seq1, 
       Round(sun_sales1 / sun_sales2, 2), 
       Round(mon_sales1 / mon_sales2, 2), 
       Round(tue_sales1 / tue_sales2, 2), 
       Round(wed_sales1 / wed_sales2, 2), 
       Round(thu_sales1 / thu_sales2, 2), 
       Round(fri_sales1 / fri_sales2, 2), 
       Round(sat_sales1 / sat_sales2, 2) 
FROM   (SELECT wswscs.d_week_seq d_week_seq1, 
               sun_sales         sun_sales1, 
               mon_sales         mon_sales1, 
               tue_sales         tue_sales1, 
               wed_sales         wed_sales1, 
               thu_sales         thu_sales1, 
               fri_sales         fri_sales1, 
               sat_sales         sat_sales1 
        FROM   wswscs, 
               date_dim 
        WHERE  date_dim.d_week_seq = wswscs.d_week_seq 
               AND d_year = 1998) y, 
       (SELECT wswscs.d_week_seq d_week_seq2, 
               sun_sales         sun_sales2, 
               mon_sales         mon_sales2, 
               tue_sales         tue_sales2, 
               wed_sales         wed_sales2, 
               thu_sales         thu_sales2, 
               fri_sales         fri_sales2, 
               sat_sales         sat_sales2 
        FROM   wswscs, 
               date_dim 
        WHERE  date_dim.d_week_seq = wswscs.d_week_seq 
               AND d_year = 1998 + 1) z 
WHERE  d_week_seq1 = d_week_seq2 - 53 
ORDER BY d_week_seq1;

выполнился за 4:33 минуты, Query3 за 3.6, Query4 за 32 минуты.

Если кому-то интересны настройки, под катом мои заметки по созданию кластера. В принципе там лишь пара gcloud команд и настройка HIVE_SERVER2_THRIFT_PORT.

Заметки

вариант one node cluster:
gcloud dataproc --region europe-north1 clusters create test1
--subnet default
--bucket tape1
--zone europe-north1-a
--single-node
--master-machine-type n1-highmem-8
--master-boot-disk-size 500
--image-version 1.3
--initialization-actions gs://dataproc-initialization-actions/hue/hue.sh
--initialization-actions gs://dataproc-initialization-actions/zeppelin/zeppelin.sh
--initialization-actions gs://dataproc-initialization-actions/hive-hcatalog/hive-hcatalog.sh
--project 123

вариант на 3 ноды:
gcloud dataproc --region europe-north1 clusters
create cluster-test1 --bucket tape1
--subnet default --zone europe-north1-a
--master-machine-type n1-standard-1
--master-boot-disk-size 10 --num-workers 2
--worker-machine-type n1-standard-1 --worker-boot-disk-size 10
--initialization-actions gs://dataproc-initialization-actions/hue/hue.sh
--initialization-actions gs://dataproc-initialization-actions/zeppelin/zeppelin.sh
--initialization-actions gs://dataproc-initialization-actions/hive-hcatalog/hive-hcatalog.sh
--project 123

gcloud compute --project=123
firewall-rules create allow-dataproc
--direction=INGRESS --priority=1000 --network=default
--action=ALLOW --rules=tcp:8088,tcp:50070,tcp:8080,tcp:10010,tcp:10000
--source-ranges=xxx.xxx.xxx.xxx/32 --target-tags=dataproc

at master node:
sudo su — vi /usr/lib/spark/conf/spark-env.sh
change: export HIVE_SERVER2_THRIFT_PORT=10010

sudo -u spark /usr/lib/spark/sbin/start-thriftserver.sh

To be continued…

Автор: Yo!

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js