Skip to content

choseenonee/misis-mirea-salut

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Решение команды "MISIS x MIREA SALUT!"

Команда

Александр, Frontend developer

Заман, Backend, Team Lead

Николай, Backend

Вадим, Frontend

Даниил, Designer

Стек приложения

Бэкенд: фреймворк Gin, база данных: PostgreSQL (Citus, используемый в Micosoft) Docker, Docker-compose

Фронтенд: React, JavaScript

Решение

Реализован swagger бэкенда админ-панели, сервиса отдачи цен, а так же фронтенд. Также доступна видео-демонстрация работы платформы

Product features

  • Управление матрицами
    • Изменение
      • История изменений (history)
      • Детальное сравнение двух матриц (аналог git diff)
      • Просмотр данных в таблице (поиск по ней)
  • Аналитика
    • Интерес
      • Тенденция цен с графиком конверсии (конверсия - мок)
      • Трассировка всего приложения (jaeger)
      • Анализ (графики на моках)
  • Профиль пользователя (мок)

Dev features

  • Algo
    • Оптимизированный поиск цен по baseline
    • Оптимизированный поиск цен по discount
  • Storage
    • Создание storage
    • Подготовка storage к production (просчитывание оптимизаций)
    • Deploy storage на production
      • Реализовать передачу через Postgres
    • Просмотр текущего storage (выбранного)
  • Price
    • Получение
    • Быстрое обновление
      • Полностью атомарное обновление
        • Идея реализации атомарного обновления
  • Deployment
    • Dockerfiles (front, admin panel back, price api back)
    • Распределённая Citus PostgreSQL
      • Шардирование (позволяет сильно оптимизировать нагрузку на postgres)
    • k8s
      • Оркестрация "подмены" текущего storage на новый
      • Перезапуск price api при его "смерти"
        • Price api back сам получает текущий storage при перезапуске

Документация

Алгоритмы:

Общий

Гипотеза: Самых нижних категорий дерева (и, скорее всего, локации) Следствие: Даже если локация есть в матрице цен, а выбранной категории вообще в ней нет, значит, пары (локация, категория) вообще нет Реализация: Аллоцируем 2 массива len(maxIndex-1), где maxIndex - максимальный индекс категории или локации соответственно, и высчитываем "прыжки" из тех локаций/категорий (не пар, а одиночных значений!) которые ВООБЩЕ не встречаются в baseline матрице. Таким образом, мы гораздо быстрее (не делая запрос в postgres) пропускаем несколько шагов (если прыгнули на 3 категории выше и на 2 локации - 6 лишних запросов в БД), таким образом уменьшая нагрузку на postgres и увеличивая скорость.

Скидочный

Гипотеза: Суммарный размер скидочных матриц ощутимо меньше размера baseline матриц Слествие: Савайте засунем все скидочные в hashMap?? Реализация: map[discountMatrixName]map[locationID]map[categoryID]int - price

Доставка до price api nodes

Citus

  1. Используется в Microsoft
  2. Управляет шардированием и репликацией
  3. По источникам из доклада Microsoft Citus в 300 раз быстрее при сложно запросе с JOIN и sum в таблице, в которой более 500 миллионов строк
  4. С июня 2022 поддерживае query from every node, что позволит не обращаться к master'у, а делать запросы к localhost с price api node, что облегчит нагрузку на сеть и увеличит скорость
  5. С официального сайта: "...2 million records per core in a second applies to Citus, and that additionally, because of our horizontal scale you can expect 2 million per core in your Citus cluster...", что говорит нам о том, что это решение более чем удовлетворительно для 2 million rpm

Идея

Каждая price nod'а имеет свой postgres, который подключён к master'у. Также, каждая price node имеет в runtime название baselineMatrix и []string{discountMatrices}, чтобы понимать, к каким именно матрицам обращаться в Postgres. При изменении storage, мы сначала кладём новые матрицы в Postgres, высчитываем для них оптимизацию по алгоритму, затем кладём оптимизации в postgres (jsonb) и только потом говорим k8s, который будет дёргать ручки каждой price node (ретраить), чтобы она начала отдавать данные из новой матрицы. Из-за citus изменение postgres будет происходить транзакционно. Таким образом, сам момент изменения - это лишь подмена полей структуры в runtime. Из этого не реализован сам citus, k8s и get оптимизации алгоритма из postgres, мы успели сделать так, что preparedStorage отсылается на nodes и там кладётся в структуру, которая ждёт экзекуции.

About

IT purple hack

Resources

Stars

Watchers