Написать пост

Как снизить нагрузку на CRM-систему

Рассказали, как справляемся с нагрузкой внутренней CRM-системы: какие технологии и практики используем и почему.

Как снизить нагрузку на CRM-систему
Я занимаюсь разработкой 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, и скорость возвращается.

Так мы решили проблемы с нагрузкой

Было приятно поделиться этой информацией, если хотите погрузиться в тему детальнее, пишите вопросы в комментариях. 

Следите за новыми постами
Следите за новыми постами по любимым темам
713 открытий7К показов