Как снизить нагрузку на CRM-систему
Рассказали, как справляемся с нагрузкой внутренней CRM-системы: какие технологии и практики используем и почему.
814 открытий9К показов
Вячеслав Артамонов
Специалист Департамента инженерной экспертизы и инструментов разработки
Я занимаюсь разработкой CRM-системы, которая собирает, связывает и анализирует информацию о клиентах. Благодаря ей мы можем создавать рекламные предложения и предоставлять важную для банка информацию таргетированно — и быть уверены, что клиент видит в ленте именно то, что нужно (или что-то, что настолько понравится, что станет нужным). В этом тексте расскажу, как мы снижаем нагрузку на CRM-систему, и разберу тонкости разработки.
Как выглядит наша CRM-система
Мы используем микросервисную архитектуру, микросервисы в основном написаны на Java. Маршрутизатором трафика работает Traefik: он собирает в себя все запросы и определяет, в какой микросервис, в какой API, отправлять реквест. Схема работы выглядит так:
Клиент —> Traefik —> (mcp-api-cleaner, mcp-reseration, mcp-proressing)
Микросервисы взаимодействуют с NoSQL и Redis, из которой информация попадает в топики Kafka и дальше в mySQL. Данные хранятся до 90 дней и после удаляются.
Благодаря такой логике клиенты получают ответ более быстрый, чем при работе с SQL базами данных .
Redis взяли по нескольким причинам
Первая: в банковском секторе нужна скорость. Вторая — у Redis быстрое и удобное взаимодействие с Java. Третья — это очень популярная система управления базами данных и применяется во многих компаниях.
Но у работы с ней есть нюансы. Погнавшись за скоростью, можно не рассчитать нагрузку, что фатально повлияет на работу приложения.
Мы тоже столкнулись со сложностями
При экспоненциальном росте нагрузки на CRM-систему Redis переполнялся и падал с неопределенной периодичностью. Изучив проблему, мы поняли, что в базе копятся записи с одинаковым ключом.
Например, мы провели тренинг, на котором сотрудники выполняли одни и те же действия: зашли в профиль, выполнили задачи А и Б и так далее. Система проанализировала контакты и объединила пользователей по интересам. В результате мы получили дерево из тысяч записей с одинаковым ключом. Мало того что это увеличило нагрузку на аналитическую систему и замедлило работу приложения, так еще и подвергло риску отказоустойчивость внутри контура банка.
Первое, что пришло в голову — создать отдельный стенд для обучения, но глобально проблему это бы не решило, потому что заранее узнать, на каком аккаунте возникнет рост, мы не сможем. Да и создание такого демостенда — накладно и не очень честно по отношению к обучаемым, потому что учеба должна проходить на реальным платформе с реальными примерами.
Также думали и ограничить коммуникацию с одним пользователем в рамках какого-то времени, но это доставило бы неудобства реальным пользователям: мы могли заафектить реальных клиентов, к тому же при каждой записи получать COUNT по ID было бы очень дорого.
Последняя идея, пришедшая к нам, была такой: искать высоконагруженные ID в mySQL и уже потом удалять их из Redis. Но это бы тоже не сработало, потому что постоянно сканировать счетчик ID долго и дорого.
Не найдя комфортного решения на текущей архитектуре, мы начали и тестировать другие инструменты
Взяли MongoDB, это тоже NoSQL база данных, которая хранит информацию не в кэше, а в формате BSON, в виде документов, содержащих пары ключ-значение. Мы сравнили скорость работы с Redis и выяснили, что MongoDB работает медленнее. Поэтому остановились на компиляции Redis и MongoDb с помощью паттерна Cache aside. На тестирование ушло несколько месяцев.
Схема простая: данные попадают в Redis и сразу же записываются в MongoDB. Так мы получаем дублированный кэш с разным временем жизни. На стороне Redis данные хранятся ограниченное время, пару дней. При частых запросах мы не теряем в перформансе и не перегружаем Redis, потому что при нагрузке мы уже смело можем очищать данные по определенному ID.
Клиент в это время получает информацию из MongoDB (да, информация придет чуть позже, это медленнее процентов на 15, но решает проблему с нагрузкой).
На перформансе, при частых запросах, потерь в скорости почти нет: даже если данные успели стереться из Redis, они не превышают 10%. В дальнейшем данные уже попадают в Redis, и скорость возвращается.
Так мы решили проблемы с нагрузкой
Было приятно поделиться этой информацией, если хотите погрузиться в тему детальнее, пишите вопросы в комментариях.
814 открытий9К показов