You are on page 1of 19

Державний університет «Одеська Політехніка»

Інститут комп’ютерних систем


Кафедра інформаційних систем

Реферат
з дисципліни «Технології комп'ютерного проектування»

Тема: «Apache Kafka»

Виконала:
студентка групи АИ-202
Полянський М.О.
Перевірив:
Іванов О. В.

Одеса 2022
Зміст
Вступ.........................................................................................................................2
1. Kafka та класичні сервіси черг.........................................................................2
2. Структура даних................................................................................................8
3. Consumer Groups.............................................................................................11
4. Apache ZooKeeper..............................................................................................16
Висновки................................................................................................................17

2
Вступ

Kafka має безліч способів застосування, і кожен спосіб має свої


особливості. У цій реферативній роботі розберемо, що Kafka відрізняється
від популярних систем обміну повідомленнями; розглянемо, як Kafka
зберігає дані та забезпечує гарантію безпеки; зрозуміємо, як записуються та
читаються дані.

Apache Kafka був створений у LinkedIn, а пізніше став проектом Apache


з відкритим вихідним кодом у 2011 році, а потім першокласним проектом
Apache у 2012 році. Kafka написаний на Scala та Java. Apache Kafka – це
стійка до відмови система обміну повідомленнями на основі публікації та
підписки. Це швидкий, масштабований та розповсюджуваний дизайн.

3
1. Kafka та класичні сервіси черг

Для першого занурення в технологію порівняємо Kafka та класичні


сервіси черг, такі як RabbitMQ та Amazon SQS.

Системи черг зазвичай складаються з трьох базових компонентів:

1) сервер,
2) продюсери, які відправляють повідомлення на якусь іменовану
чергу, заздалегідь сконфігуровану адміністратором на сервері,
3) консьюмери, які зчитують ті самі повідомлення принаймні їх
появи.

Базові компоненти класичної системи черг

У веб-додатках черги часто використовуються для відкладеної обробки


подій або як тимчасовий буфер між іншими сервісами, тим самим захищаючи
їх від сплесків навантаження.

Консьюмери одержують дані з сервера, використовуючи дві різні


моделі запитів: pull або push.

4
pull-модель - консьюмери самі надсилають запит раз на n секунд на
сервер для отримання нової порції повідомлень. За такого підходу клієнти
можуть ефективно контролювати власне навантаження. Крім того, pull-
модель дозволяє групувати повідомлення в батчі, таким чином досягаючи
кращої пропускної спроможності. До мінусів моделі можна віднести
потенційну розбалансованість навантаження між різними консьюмерами, а
також більш високу затримку обробки даних.

push-модель — сервер запитує клієнта, посилаючи йому нову порцію


даних. За такою моделлю, наприклад, працює RabbitMQ. Вона знижує
затримку обробки повідомлень та дозволяє ефективно балансувати розподіл
повідомлень за консьюмерами. Але для запобігання навантаженню
консьюмерів у випадку з RabbitMQ клієнтам доводиться використовувати
функціонал QS, виставляючи ліміти.

Як правило, додаток пише і читає з черги за допомогою кількох


інстансів продюсерів та консьюмерів. Це дозволяє ефективно розподілити
навантаження.

5
Типовий життєвий цикл повідомлень у системах черг:

1. Продюсер надсилає повідомлення на сервер.

2. Консьюмер фетчіт (від англ. fetch - принести) повідомлення та


його унікальний ідентифікатор сервера.

3. Сервер позначає повідомлення як in-flight. Повідомлення в


такому стані зберігаються на сервері, але тимчасово не доставляються іншим
консьюмерам. Таймаут цього стану контролюється спеціальним
настроюванням.

4. Консьюмер обробляє повідомлення, дотримуючись бізнес-


логіки. Потім відправляє ack або nack-запит назад на сервер, використовуючи
унікальний ідентифікатор, отриманий раніше - тим самим підтверджуючи
успішну обробку повідомлення, або сигналізуючи про помилку.

5. У разі успіху повідомлення видаляється із сервера назавжди. У


разі помилки або таймууту стану in-flight повідомлення доставляється
консьюмеру для повторної обробки.

6
Типовий життєвий цикл повідомлень у системах черг

З базовими засадами роботи черг розібралися, тепер перейдемо до


Kafka. Розглянемо її фундаментальні відмінності.

Як і послуги обробки черг, Kafka умовно складається з трьох


компонентів:

1) сервер (інше ще називається брокер)


2) продюсери - вони надсилають повідомлення брокеру
3) консьюмери - зчитують ці повідомлення, використовуючи модель pull

Базові компоненти Kafka

Мабуть, фундаментальна відмінність Kafka від черг у тому, як


повідомлення зберігаються на брокері і як споживаються консьюмерами.

7
 Повідомлення Kafka не видаляються брокерами в міру їх
обробки консьюмерами - дані Kafka можуть зберігатися днями, тижнями,
роками.

 Завдяки цьому те саме повідомлення може бути


оброблено скільки завгодно раз різними консьюмерами і в різних
контекстах.

У цьому полягає головна міць і головна відмінність Kafka від


традиційних систем обміну повідомленнями.

Тепер давайте подивимося, як Kafka та системи черг вирішують одне й


те саме завдання. Почнемо із системи черг.

Уявимо, що є сайт, на якому відбувається реєстрація користувача. Для


кожної реєстрації ми маємо:

1) надіслати лист користувачеві


2) перерахувати денну статистику реєстрацій

У випадку RabbitMQ або Amazon SQS функціонал може допомогти нам


доставити повідомлення всім сервісам одночасно. Але за необхідності
підключення нового сервісу доведеться конфігурувати нову чергу.

8
Kafka полегшує завдання. Досить надіслати повідомлення лише один
раз, а консьюмери сервісу надсилання повідомлень та консьюмери
статистики самі вважають його за необхідності.

Kafka також дозволяє тривіально підключати нові сервіси до


стримування реєстрації. Наприклад, сервіс архівування всіх реєстрацій S3
для подальшої обробки за допомогою Spark або Redshift можна додати без
додаткового конфігурування сервера або створення додаткових черг.

Крім того, якщо Kafka не видаляє дані після обробки консьюмерами, ці


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

2. Структура даних

Напевно виникає питання: «Роз повідомлення не видаляються, то як


тоді гарантувати, що консьюмер не читатиме одні й ті самі повідомлення
(наприклад, при перезапуску)?».

Для відповіді на це питання розберемося, якою є внутрішня структура


Kafka і як у ній зберігаються повідомлення.

9
Кожне повідомлення (event або message) у Kafka складається з ключа,
значення, таймстампа та опціонального набору метаданих (так званих
хедерів).

Наприклад:

Повідомлення Kafka організовані і зберігаються в іменованих топіках


(Topics), кожен топік складається з однієї і більше партицій (Partition),
розподілених між брокерами всередині одного кластера. Подібна
розподіленість важлива для горизонтального масштабування кластера,
оскільки вона дозволяє клієнтам писати та читати повідомлення з кількох
брокерів одночасно.

Коли нове повідомлення додається до топіка, насправді воно


записується в одну з партицій цього топіка. Повідомлення з однаковими
ключами завжди записуються в ту саму партицію, тим самим гарантуючи
черговість або порядок запису та читання.

Для гарантії збереження даних кожна партиція Kafka може бути


реплікована n раз, де n - replication factor. Таким чином, гарантується
наявність кількох копій повідомлення, що зберігаються на різних брокерах.

10
Кожна партиція має «лідер» (Leader) — брокер, який працює з
клієнтами. Саме лідер працює з продюсерами і загалом віддає повідомлення
консьюмерам. До лідера здійснюють запити фоловери (Follower) - брокери,
які зберігають репліку всіх цих партицій. Повідомлення завжди
надсилаються лідеру і, у загальному випадку, читаються з лідера.

Щоб зрозуміти, хто є лідером партиції, перед записом та читанням


клієнти роблять запит метаданих від брокера. Причому можуть підключатися
до будь-якого брокеру в кластері.

11
Основна структура даних в Kafka - це розподілений, лог, що
реплікується. Кожна партиція - це і є той самий лог, що реплікується, який
зберігається на диску. Кожне нове повідомлення, відправлене продюсером до
партиції, зберігається в «голову» цього лога і отримує свій унікальний,
монотонно зростаючий offset (64-бітове число, яке призначається самим
брокером).

Як ми вже з'ясували, повідомлення не видаляються з лога після


передачі консьюмерам і можуть бути вираховані скільки завгодно разів.

Час гарантованого зберігання даних на брокері можна контролювати за


допомогою спеціальних налаштувань. Тривалість зберігання повідомлень у
своїй не впливає загальну продуктивність системи. Тому абсолютно
нормально зберігати повідомлення в Kafka днями, тижнями, місяцями або
роками.

12
3. Consumer Groups

Тепер давайте перейдемо до консьюмерів та розглянемо їх принципи


роботи у Kafka. Кожен консьюмер Kafka зазвичай є частиною якоїсь
консьюмер-групи.

Кожна група має унікальну назву та реєструється брокерами у кластері


Kafka. Дані з того самого топіка можуть зчитуватися безліччю консьюмер-
груп одночасно. Коли кілька консьюмерів читають дані з Kafka і є членами
однієї групи, то кожен з них отримує повідомлення з різних партій топіка,
таким чином розподіляючи навантаження.

Повернемося до нашого прикладу з топіком сервісу реєстрації та


уявімо, що сервіс відправки листів має свою власну консьюмер-групу з
одним консьюмером c1 всередині. Отже, цей консьюмер отримуватиме
повідомлення з усіх партій топіка.

13
Якщо ми додамо ще одного консьюмера в групу, то партиції
автоматично розподіляться між ними, і c1 тепер читатиме повідомлення з
першої та другої партиції, а c2 - з третьої. Додавши ще одного консьюмера
( c3 ), ми досягнемо ідеального розподілу навантаження, і кожен з
консьюмерів у цій групі читатиме дані з однієї партиції.

14
А ось якщо ми додамо до групи ще одного консьюмера ( c4 ), то він не
буде задіяний в обробці повідомлень взагалі.

Важливо зрозуміти: усередині однієї консьюмер-групи партиції


призначаються консьюмерам унікально, щоб уникнути повторної обробки.

Якщо консьюмери не справляються з поточним обсягом даних, слід


додати нову партицію в топік. Тільки після цього консьюмер C4 розпочне
свою роботу.

Механізм партиціонування є нашим основним інструментом


масштабування Kafka. Групи є інструментом стійкості до відмови.

До речі, як ви думаєте, що буде, якщо один із консьюмерів у групі


впаде? Цілком вірно: партиції автоматично розподіляться між
консьюмерами, що залишилися в цій групі.

Додавати партиції до Kafka можна на льоту, без перезапуску клієнтів


або брокерів. Клієнти автоматично виявлять нову партицію завдяки
вбудованому механізму оновлення метаданих. Проте, слід пам'ятати дві
важливі речі:

1. Гарантія черговості даних - якщо ви пишете повідомлення з


ключами і хешує номер партиції для повідомлень, виходячи із загального
числа, то при додаванні нової партиції ви можете просто зламати порядок
цього запису.

2. Партії неможливо видалити після їх створення, можна видалити


тільки весь топік цілком.

І ще неочевидний момент: якщо ви додаєте нову партицію на продажі,


тобто в той момент, коли в топік пишуть повідомлення продюсери, то
важливо пам'ятати про налаштування auto.offset.reset=earliestв консьюмері,
інакше у вас є шанс втратити або просто не обробити шматок даних, що

15
записалися в нову партію до того, як консьюмери оновили метадані по топіку
і почали читати дані з цієї партиції.

Крім цього, механізм груп дозволяє мати кілька незв'язаних між собою
додатків, що обробляють повідомлення.

Як ми обговорювали раніше, можна додати нову групу консьюмерів до


того ж топіка, наприклад, для обробки та статистики реєстрацій. Ці дві групи
читатимуть одні й самі повідомлення з топіка тих самих івентів реєстрацій —
у своєму темпі, зі своєю внутрішньою логікою.

А тепер, знаючи внутрішній пристрій консьюмерів у Kafka, давайте


повернемося до первісного питання: «Як ми можемо позначити
повідомлення в партиції, як оброблені?» .

Для цього Kafka надає механізм консьюмер-офсетів. Як ми пам'ятаємо,


кожне повідомлення партиції має свій, унікальний, монотонно зростаючий
офсет. Саме цей офсет використовується консьюмерами для збереження
партицій.

16
Консьюмер робить спеціальний запит до брокера, так званий offset-
commit із зазначенням своєї групи, ідентифікатора топік-партиції та, власне,
офсету, який має бути позначений як оброблений. Брокер зберігає цю
інформацію у своєму власному спеціальному топіку. При рестарті консьюмер
запитує сервера останній закоммічений офсет для потрібної топік-партиції, і
просто продовжує читання повідомлень з цієї позиції.

У прикладі консьюмер у групі email-service-group, що читає


партицію p1 у топіці registrations, успішно обробив три повідомлення з
офсетами 0, 1 і 2. Для збереження позицій консьюмер робить запит до
брокера, комітя офсет 3. У разі рестарту консьюмер запросить свою останню
закоммічену позицію у брокера і отримає у відповіді 3. Після чого почне
читати дані цього офсета.

Консьюмери вільні комити абсолютно будь-який офсет (валідний, який


дійсно існує в цій топік-партиції) і можуть починати читати дані з будь-якого
офсета, рухаючись вперед і назад у часі, пропускаючи ділянки лога або
обробляючи їх заново.
17
Ключовий для розуміння факт: у момент часу може бути лише один
закоммічений офсет для топік-партиції у консьюмер-групі. Іншими словами,
ми не можемо закоммітити кілька офсетів для однієї і тієї ж топік-партиції,
емулюючи якимось чином вибіркове acknowledgment (як це робилося в
системах черг).

Припустимо, що обробка повідомлення з офсетом 1 завершилася


помилково. Проте ми продовжили виконання нашої програми в консьюмері
та запроцесували повідомлення з офсетом 2 успішно. У такому разі перед
нами стоятиме вибір: який офсет закоммітити — 1 або 3. У цій системі ми
рекомендували б закоммітити офсет 3, додавши при цьому функціонал, що
відправляє помилкове повідомлення в окремий топик для повторної обробки
(ручної або автоматичної). Подібні алгоритми називаються Dead letter queue.

Зрозуміло, консьюмери, що у різних групах, можуть мати різні


закоммічені офсети для однієї й тієї ж топик-партиции.

4. Apache ZooKeeper

Насамкінець слід згадати про ще один важливий компонент кластера


Kafka - Apache ZooKeeper.

ZooKeeper виконує роль консистентного сховища метаданих та


розподіленого сервісу логів. Саме він здатний сказати, чи живі ваші брокери,
який з брокерів є контролером (тобто брокером, який відповідає за вибір
лідерів партій), і в якому стані знаходяться лідери партій та їх репліки.

У разі падіння брокера саме в ZooKeeper контролером буде записано


інформацію про нових лідерів партицій. Причому з версії 1.1.0 це буде
зроблено асинхронно і це важливо з точки зору швидкості відновлення
кластера. Найпростіший спосіб перетворити дані на гарбуз - втрата
18
інформації в ZooKeeper. Тоді зрозуміти, що й звідки треба читати, буде дуже
складно.

В даний час ведуться активні роботи з рятування Kafka від залежності у


вигляді ZooKeeper, але поки він все ще з нами (якщо цікаво, подивіться
на Kafka improvement proposal 500 , там детально розписаний план рятування
від ZooKeeper).

Важливо пам'ятати, що ZooKeeper є ще однією розподіленою системою


зберігання даних, за якою необхідно стежити, підтримувати і оновлювати
при необхідності.

Традиційно ZooKeeper розкочується окремо від брокерів Kafka, щоб


розділити межі можливих відмов. Пам'ятайте, що падіння ZooKeeper – це
майже падіння всього кластеру Kafka. На щастя, навантаження на ZooKeeper
за нормальної роботи кластера мінімальне. Клієнти Kafka ніколи не
коннектяться до ZooKeeper прямо.

Висновки

При виконанні реферативної роботи було розглянуто та досліджено


технологію Kafka. Дослідження було націлене на те, як Kafka зберігає дані та
забезпечує гарантію безпеки. Зрозуміли, як записуються та читаються дані.

19

You might also like