Як ми робили ядро ​​інвестиційного бізнесу "Альфа-Банку" на базі Tarantool

Як ми робили ядро ​​інвестиційного бізнесу "Альфа-Банку" на базі Tarantool
Кадр з фильму

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

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

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

Щоб відповідати поточним потребам та закласти фундамент для майбутніх модернізацій, ми розробили ядро ​​інвест-бізнесу на основі Tarantool.

Небагато статистики. Інвестиційний бізнес «Альфа-Банку» надає брокерські послуги для фізичних та юридичних осіб щодо надання можливості торгувати на різних ринках цінних паперів, депозитарні послуги зі зберігання цінних паперів, послуги з довірчого управління для осіб з приватним та великим капіталом, послуги з випуску цінних паперів для інших компаній. Інвестиційний бізнес «Альфа-Банку» — це понад 3 тис. котирувань за секунду, які завантажуються з різних торгових майданчиків. Протягом робочого дня на ринках укладається понад 300 тис. угод від імені банку чи його клієнтів. На зовнішніх та внутрішніх майданчиках відбувається до 5 тис. виконань ордерів на секунду. При цьому всі клієнти як внутрішні, так і зовнішні хочуть бачити свої позиції в режимі реального часу.

Передісторія

Десь з початку 2000-х років наші напрямки інвестиційного бізнесу розвивалися незалежно: біржова торгівля, брокерські послуги, торгівля валютою, позабіржова торгівля цінними паперами та різними деривативами. В результаті ми потрапили у пастку функціональних колодязів. Що це таке? Кожен напрямок бізнесу має свої системи, які дублюють функції один одного. У кожної системи своя модель даних, хоча вони оперують одними й тими самими поняттями: угодами, інструментами, контрагентами, котируваннями та іншим. І оскільки кожна система розвивалася незалежно, виник різноманітний зоопарк технологій.

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

Вимоги до нового рішення

Бізнес зрозумів, що для подальшого розвитку життєво потрібна технологічна трансформація. Нам поставили завдання:

  1. Зібрати всі дані бізнесу в єдиному швидкому сховищі та в єдиній моделі даних.
  2. Цю інформацію ми не повинні втрачати чи змінювати.
  3. Потрібно версіонувати дані, тому що будь-якої миті регулятор може попросити статистику за минулі роки.
  4. Ми маємо не просто принести якусь нову, модну СУБД, а зробити платформу для вирішення бізнес-завдань.

Крім цього, наші архітектори поставили свої умови:

  1. Нове рішення має бути корпоративного класу, тобто воно має бути вже апробоване у якихось великих компаніях.
  2. Режим роботи рішення має бути mission critical. Це означає, що ми повинні бути одночасно в декількох дата-центрах і спокійно переживати відключення одного дата-центру.
  3. Система має бути горизонтально масштабованою. Справа в тому, що всі наші поточні системи тільки вертикально масштабуються, і ми вже упираємося в стелю через низьке зростання потужності заліза. Тому настав момент, коли нам для виживання потрібно мати систему, що горизонтально масштабується.
  4. Крім іншого нам сказали, що рішення має бути дешевим.

Ми пішли стандартним шляхом: сформулювали вимоги та звернулися до відділу закупівель. Звідти отримали список компаній, які загалом готові для нас це робити. Розповіли всім про завдання і від шести з них отримали оцінку рішень.

Ми в банку на слово нікому не віримо, любимо тестувати все самостійно. Тому обов'язковою умовою нашого тендерного конкурсу було проходження тестів навантаження. Сформулювали тестові завдання з навантаження, і вже три компанії з шести погодилися власним коштом реалізувати прототип рішення на базі in-memory-технологій, щоб протестувати його.

Я не розповідатиму, як ми все тестували і скільки часу це зайняло, підведу лише підсумок: кращу продуктивність в тестах навантаження показав прототип рішення на базі Tarantool від команди розробників Mail.ru Group. Ми підписали договір та розпочали розробку. Чотири людини було з боку Mail.ru Group, а від «Альфа-Банку» три розробники, три системні аналітики, solution-архітектор, власник продукту та Scrum-майстер.

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

Розробка

Насамперед ми запитали, як отримувати дані з наших поточних систем. Вирішили, що HTTP нам цілком підходить, тому що всі поточні системи спілкуються між собою, пересилаючи XML або JSON HTTP.

Ми використовуємо вбудований в Tarantool HTTP-сервер, тому що ми не маємо необхідності термінувати SSL-сесії, і його продуктивності нам вистачає за очі.

Як я вже казав, у нас всі системи живуть у різних моделях даних, і на вході нам потрібно привести об'єкт до тієї моделі, яку ми опишемо. Потрібна була мова, що дозволяє трансформувати дані. Ми вибрали імперативний Lua. Весь код для перетворення даних ми запускаємо в пісочниці - це безпечне місце, за межі якого запущений код не виходить. Для цього просто робимо loadstring потрібного коду, створюючи оточення з функціями, які не можуть нічого заблокувати або щось упустити.

Як ми робили ядро ​​інвестиційного бізнесу "Альфа-Банку" на базі Tarantool
Після перетворення дані треба перевірити на відповідність моделі, яку ми створюємо. Довго обговорювали, що повинна бути модель, яку мову використовувати для її опису. Зупинилися на Apache Avro, тому що мова проста і має підтримку Tarantool. Нові версії моделі та коду користувача можна відправляти в експлуатацію кілька разів на день хоч під навантаженням, хоч без, у будь-який час доби, і дуже швидко адаптуватися до змін.

Як ми робили ядро ​​інвестиційного бізнесу "Альфа-Банку" на базі Tarantool
Після перевірки дані потрібно зберегти. Робимо ми це за допомогою vshard (у нас георознесені репліки шардів).

Як ми робили ядро ​​інвестиційного бізнесу "Альфа-Банку" на базі Tarantool
При цьому специфіка така, що більшості систем, які надсилають нам дані, не має значення, отримали ми їх чи ні. Тому від початку ми реалізували ремонтну чергу. Що це таке? Якщо з якихось причин об'єкт не пройшов трансформацію даних або перевірку, ми все одно підтверджуємо отримання, але при цьому зберігаємо об'єкт у ремонтну чергу. Вона узгоджена, розташовується переважно сховище з бізнес-даними. Ми відразу написали для неї інтерфейс адміністратора, різні метрики та оповіщення. В результаті ми не втрачаємо даних. Навіть якщо в джерелі щось змінилося, якщо змінилася модель даних, ми це відразу виявимо і можемо адаптуватися.

Як ми робили ядро ​​інвестиційного бізнесу "Альфа-Банку" на базі Tarantool
Тепер потрібно навчитися отримувати збережені дані. Ми уважно проаналізували наші системи та побачили, що на класичному стеку з Java та Oracle обов'язково присутня якась ORM, яка перетворює дані з реляційного вигляду на об'єктний. То чому б одразу не віддавати об'єкти системам у вигляді графа? Тому ми з радістю взяли GraphQL, який задовольняв усі наші потреби. Він дозволяє отримувати дані у вигляді графів, витягувати лише те, що потрібно саме зараз. Можна навіть версіонувати API із досить великою гнучкістю.

Як ми робили ядро ​​інвестиційного бізнесу "Альфа-Банку" на базі Tarantool
Майже відразу ми зрозуміли, що даних нам мало. Зробили функції, які можна прив'язати до об'єктів у моделі — по суті поля, що обчислюються. Тобто ми прив'язуємо до поля певну функцію, яка вважає середню ціну котирування. А зовнішній споживач, який запитує дані, навіть не знає, що це поле обчислюється.

Як ми робили ядро ​​інвестиційного бізнесу "Альфа-Банку" на базі Tarantool
Реалізували систему автентифікації.

Як ми робили ядро ​​інвестиційного бізнесу "Альфа-Банку" на базі Tarantool
Потім помітили, що у нашому рішенні викристалізовується кілька ролей. Роль - це якийсь агрегатор функцій. Як правило, у ролей різний профіль використання обладнання:

  • T-Connect: обробляє вхідні з'єднання, обмежена процесором, споживає мало пам'яті, не зберігає стан.
  • IB-Core: трансформує дані, які отримує протокол Tarantool, тобто вона оперує табличками. Теж не зберігає стан і масштабується.
  • Storage: тільки зберігає дані, жодної логіки не використовує. У цій ролі реалізовані найпростіші інтерфейси. Масштабується завдяки vshard.

Як ми робили ядро ​​інвестиційного бізнесу "Альфа-Банку" на базі Tarantool
Тобто, за допомогою ролей ми відв'язали одна від одної різні частини кластера, які можна масштабувати незалежно одна від одної.

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

Тестування

Із самого початку проекту вирішили, що намагатимемося насаджувати test driven development. Модульні тести ми пишемо на Lua за допомогою фреймворку tarantool/tap, інтеграційні – на Python за допомогою фреймворку pytest. При цьому до написання інтеграційних тестів у нас залучені і розробники, і аналітики.

Як ми застосовуємо test driven development?

Якщо ми хочемо якусь нову фічу, то намагаємося спочатку написати для неї тест. Виявивши баг, обов'язково спочатку пишемо на тест і лише потім виправляємо. Спочатку так працювати важко, виникає нерозуміння з боку співробітників, навіть саботаж: «Давайте зараз швидко виправимо, зробимо щось нове, а потім покриємо тестами». Тільки це «потім» не настає майже ніколи.

Тому треба змушувати себе насамперед писати тести, просити оточуючих це робити. Повірте, test driven development приносить вигоду навіть у короткостроковій перспективі. Ви відчуєте, що вам полегшало жити. За нашими відчуттями зараз тестами покрито 99% коду. Здається, що це багато, але в нас немає жодних проблем: тести запускаються по кожному комміту.

Однак найбільше ми любимо тестування навантаження вважаємо його найважливішим і регулярно проводимо.

Розповім невелику історію про те, як ми проводили перший етап тестування навантаження однієї з перших версій. Поставили систему на ноутбук розробника, включили навантаження та отримали 4 тис. транзакцій на секунду. Гарний результат для ноутбука. Поставили на віртуальний стенд навантаження з чотирьох серверів, слабше, ніж у production. Розгорнули щонайменше. Запускаємо і отримуємо результат гірше, ніж на ноутбуці в один потік. Шок контент.

Ми дуже засмутилися. Дивимося завантаження серверів, а вони, виявляється, простоюють.

Як ми робили ядро ​​інвестиційного бізнесу "Альфа-Банку" на базі Tarantool
Дзвонимо розробникам, а вони пояснюють нам, людям, що прийшли зі світу Java, що Tarantool однопотоковий. Його може ефективно використовувати лише одне ядро ​​процесора під навантаженням. Тоді ми розгорнули на кожному сервері максимально можливу кількість інстансів Tarantool, включили навантаження та отримали вже 14,5 тис. транзакцій на секунду.

Як ми робили ядро ​​інвестиційного бізнесу "Альфа-Банку" на базі Tarantool
Ще раз поясню. Через поділу на ролі, які по-різному використовують ресурси, наші ролі, що відповідали за обробку з'єднань та трансформацію даних, завантажували тільки процесор, причому суворо пропорційно навантаженню.

Як ми робили ядро ​​інвестиційного бізнесу "Альфа-Банку" на базі Tarantool
Як ми робили ядро ​​інвестиційного бізнесу "Альфа-Банку" на базі Tarantool
При цьому пам'ять використовувалася лише під обробку вхідних з'єднань та тимчасових об'єктів.

Як ми робили ядро ​​інвестиційного бізнесу "Альфа-Банку" на базі Tarantool
А на серверах зберігання навпаки, завантаження процесора зростало, але набагато повільніше, ніж на серверах, що займаються обробкою з'єднань.

Як ми робили ядро ​​інвестиційного бізнесу "Альфа-Банку" на базі Tarantool
І споживання пам'яті зростало прямо пропорційно до завантаженого обсягу даних.

Як ми робили ядро ​​інвестиційного бізнесу "Альфа-Банку" на базі Tarantool

Сервіси

Щоб розвивати наш новий продукт саме як платформу програм, ми зробили компонент для розгортання на ній сервісів та бібліотек.

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

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

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

Старі системи

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

Як ми робили ядро ​​інвестиційного бізнесу "Альфа-Банку" на базі Tarantool
Якщо у нас щось змінюється, у ролі Storage спрацьовують своєрідні тригери і повідомлення зі змінами потрапляє до черги обробки. Воно за допомогою окремої ролі реплікатора вирушає у зовнішню систему. Ця роль зберігає стан.

Нові доопрацювання

Як ви пам'ятаєте, з погляду бізнесу ми зробили асинхронний запис. Але тут зрозуміли, що її буде недостатньо, тому що є клас систем, яким потрібно одразу отримувати відповідь про статус операції. Тому ми розширили наш GraphQL та додали мутації. Вони органічно вписалися у існуючу парадигму роботи з даними. У нас це єдина точка як для читання, так і для запису для іншого класу систем.

Як ми робили ядро ​​інвестиційного бізнесу "Альфа-Банку" на базі Tarantool
Також ми зрозуміли, що лише сервісів нам буде недостатньо, тому що бувають досить важкі звіти, які потрібно будувати раз на добу, на тиждень, на місяць. Це може займати довгий час, причому звіти можуть навіть блокувати event loop Tarantool'а. Тому ми зробили окремі ролі: scheduler та runner. Runner'и не зберігають стан. На них запускаються важкі завдання, які ми не можемо рахувати на льоту. p align="justify"> А роль scheduler стежить за розкладом запуску цих завдань, яке описано в конфігурації. Самі завдання зберігаються там, де й бізнес-дані. Коли настає підходящий час, scheduler бере завдання, віддає якомусь runner'у, той його вважає і зберігає результат.

Як ми робили ядро ​​інвестиційного бізнесу "Альфа-Банку" на базі Tarantool
Не всі завдання слід запускати за розкладом. Якісь звіти потрібно рахувати на вимогу. Як тільки ця вимога приходить, у пісочниці формується завдання та відправляється на виконання в runner. Через деякий час користувачеві асинхронно надходить відповідь, що все порахувалося, звіт готовий.

Як ми робили ядро ​​інвестиційного бізнесу "Альфа-Банку" на базі Tarantool
Спочатку ми дотримувалися парадигми збереження всіх даних, версіонуючи та не видаляючи їх. Але в житті періодично все-таки доводиться щось видаляти, переважно якусь сиру або проміжну інформацію. На основі expirationd ми зробили механізм очищення сховища від застарілих даних.

Як ми робили ядро ​​інвестиційного бізнесу "Альфа-Банку" на базі Tarantool
Також ми розуміємо, що рано чи пізно настане ситуація, коли місця для зберігання даних у пам'яті почне бракувати, проте дані треба зберігати. Для цього ми скоро зробимо дискове сховище.

Як ми робили ядро ​​інвестиційного бізнесу "Альфа-Банку" на базі Tarantool

Висновок

Ми почали із завдання щодо завантаження даних у єдину модель, витратили на її розробку три місяці. Ми мали шість систем-постачальників даних. Весь код трансформації на єдину модель становить близько 30 тис. рядків на Lua. А більшість роботи ще попереду. Часом не вистачає мотивації сусідніх команд, які багато ускладнюють роботу обставин. Якщо перед вами колись постане подібне завдання, той час, який вам здасться нормальним для її реалізації, помножте на три або навіть на чотири.

Також пам'ятайте, що проблеми в бізнес-процесах неможливо вирішити за допомогою нової СУБД, хай навіть дуже продуктивної. Що я маю на увазі? На старті нашого проекту ми створили у замовників враження, що зараз ми принесемо нову швидку БД і заживемо! Процеси підуть швидше, все буде гаразд. Насправді технології не вирішують тих проблем, які є в бізнес-процесах, тому що бізнес-процеси — це люди. І треба працювати з людьми, а не з технологіями.

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

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

У мові Lua немає нічого страшного. На ньому може навчитися писати будь-хто: Java-розробник, JavaScript-розробник, розробник на Python, фронтендер або бекендер. У нас навіть аналітики на ньому пишуть.

Коли ми розповідаємо про те, що у нас немає SQL, це наводить людей на жах. «Як ви отримуєте дані без SQL? Хіба так можна?" Звичайно. У системі класу OLTP SQL не потрібний. Є альтернатива у вигляді будь-якої мови, яка повертає вам одразу документоорієнтований вигляд. Наприклад, GraphQL. І є альтернатива у вигляді розподілених обчислень.

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

Джерело: habr.com

Додати коментар або відгук