Skip to content

Курс "Базы данных": Домашнее задание "Нереляционные БД"

License

Notifications You must be signed in to change notification settings

limitedeternity/db-homework-nosql

Repository files navigation

Домашнее задание 3

Это интеграционное задание. Здесь будет элемент программирования, но сильно меньше, чем в первом ДЗ.

Допустимый набор языков - такой же, как и в первом.

Чтобы сделать все в полном объеме, потребуются Mongo, Kafka и Redis.

Установить их можно по инструкциям на их сайтах или найти докеры.

Для доступа из клиентского кода потребуется установить клиентскую библиотеку.

Где ее взять - зависит от языка. Обычно можно узнать на сайте продукта или в языковых сообществах.

При возникновении проблем с установкой баз и/или поиском клиентской библиотеки не стесняйтесь задавать вопросы.

Мы не собираемся прокачивать петабайты под нагрузкой 10000 rps, поэтому все должно на обычном ноуте работать.

Задание 1

10 баллов

Посмотрим на датасет нью-йоркского такси с другой стороны.

Будем считать, что это некий поток событий, идущий извне. И мы организуем цепочку обработки этих данных.

Элементы организации потока событий станут основой последующих заданий.

А пока нам надо подготовить данные.

И эта подготовка станет первым и вторым заданиями.

То есть в первых двух заданиях мы будем готовить тестовую среду для последующих.

Для начала просто напишем клиентское приложение к MongoDB, которое заполнит коллекцию данными из датасета.

Принцип заполнения очень простой: все должно попасть в одну коллекцию.

Каждая поездка - в свой документ. Каждый столбец - в свой атрибут.

Только надо подготовить почву для следующих шагов:

  • назначить каждой поездке свой идентификатор. Например, uuid. Он нужен нам, чтобы идентифицировать поездку не только в рамках коллекции всех поездок

  • подумать, как сортировать поездки по времени начала и времени конца и в какой форме лучше хранить момент начала и момент окончания поездки

Задание 2

20 баллов

Напишем и исполним запрос или серию запросов в MongoDB с целью получить новую коллекцию, в которой будет в два раза больше документов, чем в первой.

Один документ будет про начало поездки, другой - про конец.

Оба должны иметь поле с идентификатором поездки.

Из полей датасета в документ про начало поездки должны войти также поля

  • VendorID

  • tpep_pickup_datetime

  • PULocationID

Остальные поля вместе с id идут в документ про окончание поездки.

Можно написать один aggregtion pipeline, а можно написать несколько запросов. Если нужен какой-то связующий код, работающий на клиенте, чтобы связать несколько запросов - это ok. Важно только, чтобы основная работа делалать в запросах, а не в клиенте.

Рассмотрите вариант использования индекса для последующего более быстрого доступа в размках задания 3.

В итоге должна получиться коллекция, по которой можно идти в порядке возрастания таймстемпов и получить поток начал и окончаний поездок.

Возможно, вам захочется завести отдельное поле, чтобы хранить время события в унифицированно именованном поле. Да, можно сделать так.

И здесь еще надо подумать про экстремальный случай поездки, закончившейся в тот же таймстемп, что и ее начало. Или даже раньше.

Это может быть ошибка данных. Сделайте что-нибудь, чтобы выкинуть такие поездки из данных.

Больше того, для большей надежности давайте выкинем все поезди короче одной минуты.

Даже если их нет, должен остаться запрос, с помощью которого вы в этом убедились.

Задание 3

25 баллов

Иммитация микросервиса, получающего данные из реального мира.

Напишите приложение, которое читает документы, сформированные в задании 2 и пишет их в топик/топики Кафки.

Один это будет топик или несколько, какие у них будут особенности конфигурирования - это должны решить и обосновать вы.

(Подсказка: там тонны пропертей для конфигурирования, но реально важны буквально несколько).

Решение должно учитывать следующее:

  • микросервис, пишущий данные в кафку должен масштабироваться в ширину

  • на принимающей стороне мы хотим читать параллельно

  • события должны отправляться с гарантией "exactly once" - с точки зрения взаимодействия с кафкой

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

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

Мы этот параллелизм разрабатывать не хотим. Мы пишем простой код, который читает документ за документом из MongoDB в порядке таймстемпов и пишет в кафку.

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

Интерфейс mongodb и вашего приложения -- часть тестовой среды, поэтому мошем считать его супернадежным и НЕ гарантировать здесь exactly once.

Будем также считать, что гипотетические параллелльно работающие экземпляры вашего приложения не обгоняют друг друга больше, чем на минуту (с точки зрения таймстемпов обрабатываемых событий).

То есть выкидывание поездок продолжительностью короче, чем одна минута, гарантирует нас от того, что завершение поездки запишется в кафку раньше, чем начало.

Оцениваемым артефактом здесь является код приложения, выбранная схема топика/топиков кафки, их конфигурация и конфигурация prodycer-а, а также краткий комментарий, поясняющий выбранную архитекутуру и конфигурациионные параметры.

Код ожидается очень простой, вся соль в архитектуре и конфигурировании.

Задание 4

20 баллов

Реализуем принимающую сторону.

Будем принимать из кафки поток событий и обновлять в редисе текущее состояние дел.

В данном задании оно будеи совсем простым, а основным фокусом будем аккуратное чтение.

Состояние будет:

  • количество активных поездок в целом

  • количество активных поездок по районам (location id)

Здесь приложение тоже должно быть очень простым: читать кафку и на каждый event что-то делать с редисом. Возможно, что-то еще сказать кафке в какой-то момент.

Никаких нитей внутри приложения не ожидается, но если запустить несколько экземпляров приложения, то входящие события должны обрабатываться параллельно (при условии, что в задании 3 все сконфигурировано правильно).

Если приложение и запустить заново, то оно должно продолжить чтение из кафки еще не прочитанных сообщений.

Считается допустимым в такой ситуации после рестарта перечитать и заново обработать уже прочитанное сообщение (которое находилось в обработке в момент убивания приложения).

Терять сообщения недопустимо.

Редис считаем супернадежным и не падающим.

Задание 5

25 баллов

Усложним принимающую сторону

Допущение о том, что при аварийном рестарте приложения событие может быть обработано заново может приводить к неточности в количестве поездок.

В плане общей общей статистики это не так существенно.

Но может быть неприятным, если мы хотим отлавливать моменты, когда в каком-то районе вообще нет активных поездок.

Или если нам странно видеть моменты, когда каличество активных поездок отрицательно.

Сделаем допущение, что от любого аварийного рестарта мы точно вылечимся в течение получаса.

И придумаем, как использовать редис, чтобы прежде обновления состояния проверить, а не было ли данное событие уже обработано. Точнее - в последние полчаса. Это уточнение важно, поскольку позволяет не хранить все поездки в редисе, а ограничиться горизонтом в 30 минут.

И здесь не ожидается сложного кода.

Задание 6

20 баллов

(бонусное задание)

И в качестве вишенки на тортик добавим возможность для каждого района определять на данный момент времени самый популярный район, в который едут из этого района.

Артефактом здесь является добавленная логика при получении события и функция, выведенная на пользовательский интерфейс, позволяющая сделать запрос и получить ответ.

Пойдет что угодно: rest, grpc, cli.

About

Курс "Базы данных": Домашнее задание "Нереляционные БД"

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published