Покупки с помощью карты стали неотъемлемым атрибутом современной жизни. В прошлом году жители нашей страны совершили более 21 миллиарда операций банковскими картами. На примере работы клиринговой системы ПС «Мир» рассмотрим, что делается, чтобы справляться с регулярно возрастающей нагрузкой. В частности, разберём, какие используются технологии и архитектурные решения.
Меня зовут Наталья Азисова, я product owner клиринговой системы в ПС «Мир». Каждое утро вторника я думаю о том, какой суперсрочной задачей нагрузить разработку, а к вечеру — как отложить её на пару месяцев. Спасает меня от праведного гнева разработки только то, что делаю я это со стилем.
Итак, что такое клиринг, как он работает и реализован на примере платежной системы «Мир» - читайте под катом.
![](https://habrastorage.org/getpro/habr/upload_files/b55/3f9/e17/b553f9e17cb97d69b49c0395181f48b0.png)
Что такое клиринг
Сначала накину контекста и расскажу, что называется термином «клиринг». Вот формальное определение: клиринг — это некий комплекс взаиморасчётов за оказанные друг другу услуги, проданные товары или ценные бумаги, основанные на безналичных расчётах. Соответственно, клиринг в платёжной системе — это взаиморасчёты по любым операциям, совершённым с помощью банковской карты.
Покажу на примере. Представим, что вы купили кофе в кофейне за 200 рублей, а ещё вам на карту друг перевёл 1 500. Получается, что с вашей карты должно уйти 200 рублей в кофейню, а 1 500 списаться с карты вашего друга и зачислиться на вашу карту. Но в моменте никакие деньги никуда не переходят. В моменте — лишь некие обязательства банков рассчитаться друг с другом, но желательно когда-нибудь потом. Ведь таких покупок кофе и переводов у них происходит по несколько миллионов в течение дня. Если бы банк оплачивал каждый стаканчик кофе, бухгалтерия не набегалась бы оформлять платёжные поручения в Центробанк. За банки всё это сделает платёжная система с помощью клиринга.
![](https://habrastorage.org/getpro/habr/upload_files/818/822/0b3/8188220b3916682b78619c509afb4cc9.png)
Сначала банк-эквайер кофейни направит в платёжную систему клиринговое сообщение с информацией о том, что по вашей карте купили кофе. Потом банк вашего друга направит клиринговое сообщение о том, что он перевёл на вашу карту деньги.
По итогу клиринговая система проведёт расчёты: 200 рублей уйдёт на счёт банка-эквайера, представляющего кофейню, 1 500 спишутся с банка вашего друга, а 1 300 рублей зачислится в ваш банк. Если сложить все эти суммы, получится ноль. Таким образом, гарантируется, что никакие деньги ниоткуда случайным образом не возникли и нигде по дороге не потерялись.
Такая итоговая информация передастся в Центробанк, и там деньги по-настоящему перейдут со счёта одного банка на счёт другого. Это и есть функция клиринга — посчитать итоговые суммы по всем карточным операциям, поступившим в платёжную систему.
Если вы когда-либо пытались посчитать свой личный или семейный бюджет, например, за месяц, то вы занимались клирингом.
Теперь, мы знаем, что такое клиринг. Вроде всё просто — складывай и вычитай суммы. Но где большие нагрузки-то?
![](https://habrastorage.org/getpro/habr/upload_files/902/a4c/11b/902a4c11b8ad95202302517653bf47d2.png)
Клиринговая система — это высоконагруженная система. Это проявляется в том, что каждый день система:
Обрабатывает более 50 миллионов операций;
Генерит более 3 000 различных файлов и отчётов для банков;
Получает данные из большого количества ключевых систем Мир Plat.Form, а также является источником транзакционных данных;
Обеспечивает строгий SLA на каждом этапе работы. Так как важно, чтобы все расчёты происходили точно, в срок и без ошибок.
Основные задачи
Основные задачи, которые стоят перед клиринговой системой:
Обработка большого потока данных;
Учёт всех жёстких дедлайнов на каждом этапе работы;
Соблюдение точности расчётов;
Сохранение качества итоговых архивных данных.
Архитектура
Верхнеуровневая архитектура выглядит следующим образом:
![](https://habrastorage.org/getpro/habr/upload_files/9a0/4bd/fd1/9a04bdfd18b16595614a17faa845d0e4.jpg)
Ядро реализовано на java. Данные поступают на вход в двух форматах: по RESTу из различных систем источников и в виде файлов в формате платёжной системы «Мир» от банков. Однако, вне зависимости от источника, они все преобразуются в JSON-сообщение и сохраняются в базу. Хранятся тоже в формате JSON, но ключевые поля раскладываются по таблицам для быстрого доступа к ним.
Результаты обработки клиринга отправляются в банки в виде различного набора файлов. Это текстовые файлы в разных кодировках и xml-отчёты. Итоговые транзакционные данные отправляются в архив с помощью ETL.
Тайминги работы системы
![](https://habrastorage.org/getpro/habr/upload_files/69f/c1c/253/69fc1c2539ab89d7d25e2f1be5b15d96.png)
Клиринговая система принимает данные на вход 24/7, но временной регламент всё же есть. Основу этого регламента составляет период с 9 утра одного дня до 9 утра следующего, который называется операционным днём. Внутри этого операционного дня есть определённые этапы работы, которые строго ограничены дедлайнами для внешних потребителей.
Разберём эти этапы подробнее.
Этапы работы системы
Загрузка данных
Начнём с загрузки. Есть два основных канала получения данных: REST и файлы.
![](https://habrastorage.org/getpro/habr/upload_files/4b2/075/c1a/4b2075c1a98db24312d92422486c55ed.png)
С RESTом всё достаточно просто: получаешь JSON из SWAGGER выгрузки, маппишь в свой красивый JSON и получаешь профит. Но с файлами чуууть сложнее… Ведь это не в чистом виде текстовый файл в кодировке ASCII, а свой собственный формат ПС «МИР» на основе международного протокола ISO-8583 (1987-93). Этот формат представляет собой текстовый файл, в котором применяется кодировка ASCII, бинарные данные, а для нелатинских символов используются символы Unicode в кодировке UTF-8.
Вроде всё просто. Нужно получить файл, распарсить, провалидировать его по всем правилам платёжной системы, откинуть лишнее, смаппить в JSON и сохранить в базу. Ничего сложного, но, имея несколько десятков гигабайтных файлов за раз, необходимо решать вопросы производительности.
Были упомянуты протокол ISO 8583 и кодировка ASCII. Внимательный и быстро гуглящий читатель может задать вполне резонный вопрос: почему такая молодая платёжная система, относительно других международных, использует такие не суперсовременные стандарты?
![](https://habrastorage.org/getpro/habr/upload_files/f71/836/4c5/f718364c5b370e57fb58b3c3d8c80bb6.jpg)
Дело в том, что мировая финансовая индустрия — это большой неповоротливый динозавр, который не любит резких движений. Любые изменения в существующих системах влекут за собой большие финансовые риски. Чтобы банкам или другим финансовым институтам их совершать не пришлось, при проектировании платёжной системы «Мир» были использованы широко распространённые на рынке стандарты и технологии. Это также существенно экономит ресурсы разработки процессингового ПО для всех участников рынка.
Валидация
![](https://habrastorage.org/getpro/habr/upload_files/190/5ae/7f8/1905ae7f8a540569316899f4fc75213a.png)
Вернёмся к валидации файлов. Для неё написан domain specific language на Groovy. Почему Groovy? В основном для лёгкости поддержки системы.
Успешно прошедшие валидацию транзакции переходят на этап обогащения данных.
Обогащение данных
![](https://habrastorage.org/getpro/habr/upload_files/6eb/0a4/c2c/6eb0a4c2cc76b69cf57edd9eb219e500.png)
Что понимается под обогащением? Вот несколько примеров: это различные конвертации покупок, снятия наличных из валют в рубли или наоборот. Это также расчёты разного рода дополнительных сумм по правилам платёжной системы. Кроме этого, если заплатить, например, смартфоном или другим переносным устройством в магазине или кофейне, то в таком случае банк-эквайер на месте не знает реальный номер вашей карты, а только токен устройства, к которому привязана эта карта. Платёжная система должна определить реальный номер карты по токену и передать эту информацию в ваш банк.
Все эти обогащения данных реализованы внутри клиринговой системы с помощью вспомогательных модулей.
Вспомогательные модули
![](https://habrastorage.org/getpro/habr/upload_files/a43/968/67b/a4396867b5d0c49785834746d14ae73b.png)
Большой, единый сервис ядра обращается к модулям за данными при необходимости. Взаимодействие с модулями построено по RESTу. Этот вариант нам подходит, так как данные или команды, которые мы передаём в модули, должны обрабатываться дискретно.
Модули у нас написаны на KOTLIN.
![](https://habrastorage.org/getpro/habr/upload_files/e2b/e2a/d31/e2be2ad317676d826264daaed04f5cbc.png)
Почему Kotlin? На самом деле, особых альтернатив не было, так как необходимо оставаться в стеке JVM. Плюс на Kotlin’е намного проще реализовывать код, когда много бизнес-логики. Код проще читается и получается более лаконичным. Также Kotlin поддерживает наш эксперимент по внедрению новых технологий.
На этапе обогащения много миллионов транзакций поступают в клиринговую систему. Масштабирование нагрузки вертикальное, что влечёт за собой постоянную утилизацию ресурсов, а это многопоточность. Решалась эта проблема с помощью фреймворка Akka с его акторной системой.
Akka
![](https://habrastorage.org/getpro/habr/upload_files/492/51a/49a/49251a49acf3a52d3e819c31c0e6c61d.png)
Akka — это готовая среда для построения высоконагруженных систем. Для обработки каждого поступающего в клиринговую систему файла создаётся отдельный актор. Плюс для каждой отдельной транзакции также создаётся отдельный актор или группа акторов, что позволяет реализовать потоковую и независимую обработку всех входящих в клиринговую систему данных.
Некоторые акторы работают как сервисы, то есть выступают в роли некоего окошка для обращения к внешним модулям. Например, так работает тот же модуль конвертации или детокенизации.
Статичные акторы, которые выполняют общие функции обработки, могут достаточно долго хранить свои состояния, что опять же позволяет быстрее прокидывать транзакции дальше.
Загрузка в операционный день прекращается в 9 утра. Загрузка засыпает, просыпается клиринг.
Клиринг
![](https://habrastorage.org/getpro/habr/upload_files/f90/313/c65/f90313c656e1c5f78e2b60412255528d.png)
На этапе клиринга мы должны сложить и вычесть в среднем 50 миллионов транзакций в сутки, сгенерировать итоговые суммы с различного рода агрегациями или срезами данных для банков. И в конце передать эти итоги в Центробанк строго до 15 часов того же дня, что бы ни произошло.
На этапе клиринга также есть некий комплекс независимых проверок, дабы не ошибиться в расчётах. Мы не совсем доверяем самим себе, поэтому дополнительно перепроверяем рядышком, что же мы насчитали.
Выгрузка файлов
Как только всё посчитано, мы молодцы и, наконец-то, можем сообщить банкам, как прошёл день: сколько денег они должны получить или отдать, и какие транзакции совершены держателями их карт. И ещё много-много разной информации.
![](https://habrastorage.org/getpro/habr/upload_files/470/c58/f49/470c58f49b52726505c9256726997c57.png)
Всё это выгружается в банки различным набором файлов, отчётов и прочего. Среднее количество файлов, которые генерируются и отправляются в банки каждый день, составляет около 3000. Самые жирные могут весить по 4 гигабайта.
Задачи этапа выгрузки файлов всё те же: уложиться в тайминги и не вывалиться по памяти. Для этого опять используем Groovy как шаблон для формирования каждого отчёта и параллелим выгрузку по типам этих файлов. По завершению этапа выгрузки данных, прекращается строгая бизнес-цепочка, после чего снова можно начать принимать транзакции на вход.
Рабочее окно непосредственно для этапа загрузки данных существенно больше, чем для всех остальных этапов. Поэтому на него мы переносим максимум работы с транзакциями, чтобы после того, как они будут сохранены в базу, их больше не модифицировать.
Такой подход позволяет нам сэкономить время для последующей работы с данными.
Выгрузка в архив
![](https://habrastorage.org/getpro/habr/upload_files/dfa/82c/3b2/dfa82c3b2cafd0419ecf738906602ce2.png)
Так как мы мастер-система по расчётным транзакционным данных, то, естественно, мы должны поделиться всем этим богатством с остальными системами. Никого не удивим тем фактом, что для этого отправляем транзакции в архив.
Что решается на этом этапе?
Так как все транзакции хранятся в базе в формате JSON, то нужно преобразовать их обратно из JSON в поля протокола платёжной системы, разложить всё это по таблицам и не потерять ничего по дороге. С этой функцией отлично справляется отдельный модуль выгрузки в архив, который не зависит от текущего состояния клиринговой системы. Такая условно параллельная этапу загрузки работа модуля существенно экономит время доставки транзакционных данных потребителям.
Инфраструктура
За последнее время, думаю, многие разобрались, чем отличаются карты в вашем кошельке, кроме дизайна и количества получаемого кэшбека. От того, к какой платёжной системе принадлежит ваша карта, зависят самые обычные операции в жизни, начиная от покупки кофе смартфоном до оплаты любимых сервисов в Интернете. В Мир Plat.Form делается всё, чтобы важные для каждого вещи не нарушались. С февраля по май нагрузка на систему Мир Plat.Form выросла более, чем на 40%.
Сейчас в день обрабатывается столько же транзакций, сколько в период последних новогодних праздников. А все понимают, как все сходят с ума в поисках подарков в эти дни.
Помимо программных решений, за надёжность отвечает инфраструктура.
![](https://habrastorage.org/getpro/habr/upload_files/a00/730/3eb/a007303eb4b25cad5ed136fdaf29b60f.png)
Сервера расположены в двух центрах обработки данных для георезервирования. В одном ЦОДе расположены активные сервера, во втором — резервные. Поэтому становится особо не важно, что происходит с одним из ЦОДов, пусть это пожар, потоп или хоть страшный экскаватор, который разрывает кабели. В течение короткого времени можно переключиться на второй ЦОД и продолжить шуршать транзакциями.
Для базы данных используется холодное резервное копирование. Такой вариант подходит, так как это не онлайн система, и есть опция повторить несколько предыдущих этапов заново. При условии, конечно, что всё укладывается в тайминги.
Релиз
Помимо внешних факторов, вроде роста нагрузки и доступности ЦОДов, на стабильность работы системы влияют всеми любимые релизные фичи. Хоть в моей команде QA, конечно же, все самые белые и пушистые, но всё же иногда они заставляют мой глаз подёргиваться. В нашей команде работа над релизами не заканчивается с завершением этапов интеграционного, функционального и прочих тестирований. У нас в команде есть такой процесс, как тестирование в эксплуатации.
Тестирование в эксплуатации
![](https://habrastorage.org/getpro/habr/upload_files/671/3de/ec0/6713deec04380d28d723293ea21355d5.png)
Представьте двух бендеров. Один из них красивый и с пивасом — наш идеальный прод. Второй — это прод-лайк стенд, на котором установлена новая версия релиза. Мы берём этих двух бендеров и сравниваем между собой. Сравнивается абсолютно всё: отчёты по содержимому и по их количеству, сами транзакции с точностью до полей. И ещё много-много чего. Основная задача — убедиться в том, что новая релизная сборка не повлияла ни на один нюанс в расчётах, не нарушена никакая интеграция и форматы исходящих файлов не изменились, то есть банки не узнают о том, что был релиз.
Итоги
![](https://habrastorage.org/getpro/habr/upload_files/27e/500/100/27e5001007e71a656178c7cd1541f5be.png)
Много парсинга и обогащения данных, которые поступают неравномерно.
От бесперебойной работы системы зависит большая часть финансовой индустрии в нашей стране. Поэтому необходимо обеспечивать строгие дедлайны на каждом этапе работы.
При этом постоянно разрастается количество систем-источников данных, так как всё больше и больше происходит всевозможных операций с помощью карт «Мир».
На выходе генерится огромное количество файлов и отчётов по запросам банков. Причём тоже в строгие дедлайны.
Таким комплексом решений ПО, инфраструктуры и процессов гарантируется стабильность сервиса клиринговой системы.
Единственная конференция на которой можно узнать максимальные пределы технологий. Меньше, чем через 4 недели: 3000 участников, 8 секций и 120 новых докладов. Программа конференции и билеты на официальном сайте HighLoad++