1. Історія виникнення терміну BigData

Термін Big Data з'явився порівняно недавно. Google Trends показує початок активного зростання вживання словосполучення починаючи з 2011 року:

При цьому вже зараз термін не використовує лише лінивий. Особливо часто без приводу цей термін використовують маркетологи. То що таке Big Data насправді? Якщо я вирішив системно викласти і висвітлити питання, необхідно визначитися з поняттям.

У своїй практиці я зустрічався з різними визначеннями:

  • Big Data — це коли даних більше ніж 100Гб (500Гб, 1ТБ, кому що подобається).
  • Big Data — це дані, які неможливо обробляти в Excel.
  • Big Data — це дані, які неможливо обробити на одному комп'ютері.

І навіть такі:

  • Вig Data — це взагалі будь-які дані.
  • Big Data не існує, її вигадали маркетологи.

Я буду дотримуватися визначення з wikipedia:

Великі дані (англ. big data) — серія підходів, інструментів і методів обробки структурованих і неструктурованих даних величезних обсягів і значного різноманіття для отримання результатів, що сприймаються людиною, ефективних в умовах безперервного приросту, розподілу по численним вузлам обчислювальної мережі, що сформувалися наприкінці 2000-х років, альтернативних традиційним системам управління базами даних та рішенням класу Business Intelligence.

Таким чином під Big Data я розумітиму не якийсь конкретний обсяг даних і навіть не самі дані, а методи їх обробки, які дозволяють розподілено обробляти інформацію. Ці методи можна застосувати як до величезних масивів даних (таких як зміст усіх сторінок в інтернеті), так і до маленьких (таких як вміст цієї лекції).

Наведу кілька прикладів того, що може бути джерелом даних, для яких потрібні методи роботи з великими даними:

  • Логи поведінки користувачів в інтернеті
  • GPS-сигнали від автомобілів для транспортної компанії
  • Дані, що знімаються з датчиків у великому адронному колайдері
  • Оцифровані книги в Державній Бібліотеці
  • Інформація про транзакції всіх клієнтів банку
  • Інформація про всі покупки у великій рітейлі мережі тощо.

Кількість джерел даних стрімко зростає, а значить, на технології їх обробки зростає попит.

2. Принципи роботи з великими даними

Виходячи з визначення Big Data, можна сформулювати основні принципи роботи з такими даними:

1. Горизонтальна масштабованість. Оскільки даних може бути скільки завгодно – будь-яка система, яка передбачає обробку великих даних, має бути розширюваною. У 2 рази збільшився обсяг даних — у 2 рази збільшили кількість заліза в кластері і все продовжило працювати.

2. Відмовостійкість. Принцип горизонтальної масштабованості передбачає, що машин у кластері може бути багато. Наприклад, Hadoop-кластер Yahoo має більше 42000 машин. Це означає, що частина цих машин гарантовано виходитиме з ладу. Методи роботи з великими даними повинні враховувати можливість таких збоїв та переживати їх без жодних значних наслідків.

3. Локальність даних. У великих розподілених системах дані розподілені за великою кількістю машин. Якщо дані фізично знаходяться на одному сервері, а обробляються на іншому — витрати на передачу даних можуть перевищити витрати на обробку. Тому одним із найважливіших принципів проєктування BigData-рішень є принцип локальності даних — за можливостю обробляємо дані на тій же машині, на якій їх зберігаємо.

Усі сучасні засоби роботи з великими даними так чи інакше дотримуються цих трьох принципів. Для того, щоб їх дотримуватися, необхідно вигадувати якісь методи, способи та парадигми розробки засобів розробки даних. Один із класичних методів я розберу в сьогоднішній лекції.

3. MapReduce

MapReduce — це модель розподіленої обробки даних, запропонована Google для обробки великих обсягів даних на комп'ютерних кластерах. MapReduce непогано ілюструється наступним малюнком:

MapReduce

MapReduce передбачає, що дані організовані у вигляді певних записів. Обробка даних відбувається у 3 стадії:

1. Стадія Map. На цій стадії дані передробляються за допомогою функції map(), яку визначає користувач. Робота цієї стадії полягає у передобробці та фільтрації даних. Робота дуже схожа на операцію map у функціональних мовах програмування — функція користувача застосовується до кожного вхідного запису.

Функція map(), застосована до одного вхідного запису і видає безліч пар ключ-значення. Безліч — тобто може видати лише один запис, може не видати нічого, а може видати кілька пар ключ-значення. Що буде в ключі і в значенні — вирішувати користувачеві, але ключ — дуже важлива річ, оскільки дані з одним ключем у майбутньому потраплять в один екземпляр функції reduce.

2. Стадія Shuffle. Проходить непомітно для користувача. На цій стадії виведення функції map "розбирається по кошиках" — кожен кошик відповідає одному ключу виведення стадії map. Надалі ці кошики послужать входом до reduce.

3. Стадія Reduce. Кожен «кошик» зі значеннями, сформований на стадії shuffle, потрапляє на вхід функції reduce().

Функція reduce задається користувачем та обчислює фінальний результат для окремого «кошика». Безліч усіх значень, що повертаються функцією reduce(), є фінальним результатом MapReduce-завдання.

Кілька додаткових фактів про MapReduce:

  1. Всі запуски функції map працюють незалежно і можуть працювати паралельно, у тому числі на різних кластерних машинах.
  2. Всі запуски функції reduce працюють незалежно і можуть працювати паралельно, у тому числі на різних кластерних машинах.
  3. Shuffle в собі представляє паралельне сортування, тому також може працювати на різних машинах кластера. Пункти 1-3 дозволяють виконати принцип горизонтального масштабування.
  4. Функція map, як правило, застосовується на тій же машині, на якій зберігаються дані — це дозволяє знизити передачу даних через мережу (принцип локальності даних).
  5. MapReduce — це завжди повне сканування даних, жодних індексів немає. Це означає, що MapReduce погано застосовується, коли відповідь потрібна дуже швидко.

4. Приклади завдань, які ефективно вирішуються за допомогою MapReduce

Word Count

Почнемо з класичного завдання — Word Count. Завдання формулюється так: є великий корпус документів. Завдання — для кожного слова, хоча б одного разу зустрічається в корпусі, порахувати сумарну кількість разів, яку вона зустріла в корпусі.

Рішення:

Якщо маємо великий корпус документів — нехай один документ буде одним вхідним записом для MapRreduce–завдання. У MapReduce ми можемо тільки зазначати функції користувача, що ми і зробимо (використовуватимемо python-like псевдокод):

def map(doc):
for word in doc:
yield word, 1 
def reduce(word, values):
yield word, sum(values) 

Функція map перетворює вхідний документ на набір пар (слово, 1), shuffle прозоро для нас перетворює це на пари (слово, [1,1,1,1 ,1,1]), reduce підсумовує ці одиниці, повертаючи фінальну відповідь для слова.

Обробка логів рекламної системи

Другий приклад взятий із реальної практики Data-Centric Alliance.

Завдання: є csv-лог рекламної системи виду:

<user_id>,<country>,<city>,<campaign_id>,<creative_id>,<payment></p>
 
11111,PL,Warsaw,2,4,0.3
22222,PL,Krakow,2,3,0.2
13413,UA,Kyiv,4,11,0.7
… 

Необхідно розрахувати середню вартість показу реклами містами Польщі.

Рішення:

def map(record):
user_id, country, city, campaign_id, creative_id, payment = record.split(",")
payment=float(payment)
if country == "PL":
yield city, payment 
def reduce(city, payments):
yield city, sum(payments)/len(payments)

Функція map перевіряє, чи потрібний нам цей запис, і якщо потрібний, залишає лише потрібну інформацію (місто та розмір платежу). Функція reduce обчислює фінальну відповідь по місту, маючи список усіх платежів у цьому місті.