GithubHelp home page GithubHelp logo

artem / 2022-highload-dht Goto Github PK

View Code? Open in Web Editor NEW

This project forked from incubos/2022-highload-dht

0.0 0.0 0.0 748.58 MB

Highload course project

License: Apache License 2.0

Shell 0.01% Java 1.08% Lua 0.01% HTML 98.86% Roff 0.04%

2022-highload-dht's Introduction

2022-highload-dht

Курсовой проект 2022 года курса "Проектирование высоконагруженных систем" VK Образования.

Этап 1. HTTP + storage (deadline 2022-09-28 23:59:59 MSK)

Fork

Форкните проект, склонируйте и добавьте upstream:

$ git clone [email protected]:<username>/2022-highload-dht.git
Cloning into '2022-highload-dht'...
...
$ git remote add upstream [email protected]:polis-vk/2022-highload-dht.git
$ git fetch upstream
From github.com:polis-vk/2022-highload-dht
 * [new branch]      master     -> upstream/master

Make

Так можно запустить тесты:

$ ./gradlew test

А вот так -- сервер:

$ ./gradlew run

Develop

Откройте в IDE -- IntelliJ IDEA Community Edition нам будет достаточно.

ВНИМАНИЕ! При запуске тестов или сервера в IDE необходимо передавать Java опцию -Xmx128m.

В своём Java package ok.dht.test.<username> реализуйте интерфейсы Service и ServiceFactory.Factory и поддержите следующий HTTP REST API протокол:

  • HTTP GET /v0/entity?id=<ID> -- получить данные по ключу <ID>. Возвращает 200 OK и данные или 404 Not Found.
  • HTTP PUT /v0/entity?id=<ID> -- создать/перезаписать (upsert) данные по ключу <ID>. Возвращает 201 Created.
  • HTTP DELETE /v0/entity?id=<ID> -- удалить данные по ключу <ID>. Возвращает 202 Accepted.

Используем свою реализацию DAO из весеннего курса 2022-nosql-lsm, либо берём референсную реализацию, если курс БД не был завершён.

Проведите нагрузочное тестирование с помощью wrk2 в одно соединение:

  • PUT запросами на стабильной нагрузке (wrk2 должен обеспечивать заданный с помощью -R rate запросов)
  • GET запросами на стабильной нагрузке по наполненной БД

Почему не curl/F5, можно узнать здесь и здесь.

Приложите полученный консольный вывод wrk2 для обоих видов нагрузки.

Отпрофилируйте приложение (CPU и alloc) под PUT и GET нагрузкой с помощью async-profiler. Приложите SVG-файлы FlameGraph cpu/alloc для PUT/GET нагрузки.

Объясните результаты нагрузочного тестирования и профилирования и приложите текстовый отчёт (в Markdown).

Продолжайте запускать тесты и исправлять ошибки, не забывая подтягивать новые тесты и фиксы из upstream. Если заметите ошибку в upstream, заводите баг и присылайте pull request ;)

Report

Когда всё будет готово, присылайте pull request со своей реализацией и оптимизациями на review. Не забывайте отвечать на комментарии в PR (в том числе автоматизированные) и исправлять замечания!

Этап 2. Асинхронный сервер (deadline 2022-10-05 23:59:59 MSK)

Вынесите обработку запросов в отдельный ExecutorService с ограниченной очередью, чтобы разгрузить SelectorThreadы HTTP сервера.

Проведите нагрузочное тестирование с помощью wrk2 с большим количеством соединений (не меньше 64) PUT и GET запросами.

Отпрофилируйте приложение (CPU, alloc и lock) под PUT и GET нагрузкой с помощью async-profiler.

Report

Когда всё будет готово, присылайте pull request с изменениями, результатами нагрузочного тестирования и профилирования, а также анализом результатов по сравнению с предыдущей (синхронной) версией.

Этап 3. Шардирование (bonus deadline 2022-10-12 23:59:59 MSK, hard deadline 2022-10-19 23:59:59 MSK)

Реализуем горизонтальное масштабирование через поддержку кластерных конфигураций, состоящих из нескольких узлов, взаимодействующих друг с другом через реализованный HTTP API. Для этого в ServiceConfig передаётся статическая "топология", представленная в виде множества координат всех узлов кластера в формате http://<host>:<port>.

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

Реализуйте один из алгоритмов распределения данных между узлами, например, consistent hashing, rendezvous hashing или что-то другое по согласованию с преподавателем.

Report

Присылайте pull request со своей реализацией поддержки кластерной конфигурации на review. Не забудьте нагрузить, отпрофилировать и проанализировать результаты профилирования под нагрузкой. С учётом шардирования набор тестов расширяется, поэтому не забывайте подмёрдживать upstream.

Этап 4. Репликация (deadline 2022-10-26 23:59:59 MSK)

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

HTTP API расширяется query-параметрами from и ack, содержащими количество узлов, которые должны подтвердить операцию, чтобы она считалась выполненной успешно.

  • ack -- сколько ответов нужно получить
  • from -- от какого количества узлов

Таким образом, теперь узлы должны поддерживать расширенный протокол (совместимый с предыдущей версией):

  • HTTP GET /v0/entity?id=<ID>[&ack=<ACK>&from=<FROM>] -- получить данные по ключу <ID>. Возвращает:

    • 200 OK и данные, если ответили хотя бы ack из from реплик
    • 404 Not Found, если ни одна из ack реплик, вернувших ответ, не содержит данные (либо самая свежая версия среди ack ответов -- это tombstone)
    • 504 Not Enough Replicas, если не получили 200/404 от ack реплик из всего множества from реплик
  • HTTP PUT /v0/entity?id=<ID>[&ack=<ACK>&from=<FROM>] -- создать/перезаписать (upsert) данные по ключу <ID>. Возвращает:

    • 201 Created, если хотя бы ack из from реплик подтвердили операцию
    • 504 Not Enough Replicas, если не набралось ack подтверждений из всего множества from реплик
  • HTTP DELETE /v0/entity?id=<ID>[&ack=<ACK>&from=<FROM>] -- удалить данные по ключу <ID>. Возвращает:

    • 202 Accepted, если хотя бы ack из from реплик подтвердили операцию
    • 504 Not Enough Replicas, если не набралось ack подтверждений из всего множества from реплик

Если параметр replicas не указан, то в качестве ack используется значение по умолчанию, равное кворуму от количества узлов в кластере, а from равен общему количеству узлов в кластере, например:

  • 1/1 для кластера из одного узла
  • 2/2 для кластера из двух узлов
  • 2/3 для кластера из трёх узлов
  • 3/4 для кластера из четырёх узлов
  • 3/5 для кластера из пяти узлов

Выбор узлов-реплик (множества from) для каждого <ID> является детерминированным:

  • Множество узлов-реплик для фиксированного ID и меньшего значения from является строгим подмножеством для большего значения from
  • При PUT не сохраняется больше копий данных, чем указано в from (т.е. не стоит писать лишние копии данных на все реплики)

Фактически, с помощью параметра replicas клиент выбирает, сколько копий данных он хочет хранить, а также уровень консистентности при выполнении последовательности операций для одного ID.

Таким образом, обеспечиваются следующие примеры инвариантов (список не исчерпывающий):

  • GET с 1/2 всегда вернёт данные, сохранённые с помощью PUT с 2/2 (даже при недоступности одной реплики при GET)
  • GET с 2/3 всегда вернёт данные, сохранённые с помощью PUT с 2/3 (даже при недоступности одной реплики при GET)
  • GET с 1/2 "увидит" результат DELETE с 2/2 (даже при недоступности одной реплики при GET)
  • GET с 2/3 "увидит" результат DELETE с 2/3 (даже при недоступности одной реплики при GET)
  • GET с 1/2 может не "увидеть" результат PUT с 1/2
  • GET с 1/3 может не "увидеть" результат PUT с 2/3
  • GET с 1/2 может вернуть данные несмотря на предшествующий DELETE с 1/2
  • GET с 1/3 может вернуть данные несмотря на предшествующий DELETE с 2/3
  • GET с ack равным quorum(from) "увидит" результат PUT/DELETE с ack равным quorum(from) даже при недоступности < quorum(from) реплик

Report

Присылайте pull request со своей реализацией поддержки кластерной конфигурации на review. Не забудьте нагрузить, отпрофилировать и проанализировать результаты профилирования под нагрузкой. С учётом репликации набор тестов расширяется, поэтому не забывайте подмёрдживать upstream.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.