ТЕХНИЧЕСКОЕ ЗАДАНИЕ
	на разработку высокопроизводительной In‑Memory Cache системы (аналог Memcached/Redis)

1. Цель проекта
Разработать высоконагруженное сетевое кэширующее хранилище типа «ключ‑значение» на языке C++ (или Rust). Система предназначена для снижения нагрузки на основную БД путём временного хранения часто запрашиваемых данных в оперативной памяти.

Ключевые целевые показатели:

Пропускная способность ≥ 10 000 операций/сек.

Задержка (p99) < 10 мс.

Поддержка ≥ 1 000 одновременных клиентских соединений.

Потокобезопасность и отказоустойчивость (graceful shutdown).

2. Функциональные требования
2.1. Базовые команды
Реализовать следующий минимальный набор команд (текстовый протокол поверх TCP):

SET key value [EX seconds] – сохранить значение, опционально с временем жизни.

GET key – получить значение по ключу, вернуть ошибку, если ключ отсутствует.

DELETE key – удалить ключ.

EXISTS key – проверить существование ключа.

(опционально) INCR key – инкремент числового значения.

(опционально) STATS – вывести статистику (хиты/промахи, использовано памяти и т.п.).

2.2. Управление памятью и вытеснение

Реализовать политику вытеснения LRU (Least Recently Used) или LFU.

При превышении заданного лимита памяти (задаётся в конфиге) автоматически удалять наименее приоритетные элементы.

Для значений с TTL – ленивое удаление при доступе + фоновый сборщик с заданным интервалом.

2.3. Сетевой протокол

	Сервер должен принимать TCP-соединения, поддерживать keep‑alive.

Обрабатывать несколько запросов в рамках одного соединения.

Формат ответов: простой текстовый (например, +OK\r\n, $<len>\r\n<data>\r\n, -ERR ...\r\n).

2.4. Многопоточность

Обработка параллельных запросов должна быть потокобезопасной.

Рекомендуется шардирование данных по нескольким независимым кэш‑инстансам (каждый в своём потоке) для минимизации блокировок.

3. Нефункциональные требования (чёткие метрики)
Параметр	Целевое значение
Пропускная способность (GET)	≥ 10 000 RPS (при 1000 клиентах, размер значения ~100 байт)
Задержка (p99)	< 10 мс при 80% нагрузке
Количество одновременных соединений	≥ 1 000 (постоянных)
Максимальный размер кэша	Конфигурируется (например, 1 ГБ, 4 ГБ)
Graceful shutdown	По сигналу SIGTERM сервер завершает текущие запросы и корректно закрывает соединения за < 1 сек
Логирование	Асинхронное, с ротацией файлов
4. Архитектурные требования (общие)
Сетевой I/O – использовать мультиплексирование (epoll для Linux, kqueue для macOS, IOCP для Windows) с неблокирующими сокетами.

Модель потоков – реакторный паттерн: один главный поток (акцептор) распределяет соединения по пулу воркеров, либо каждый воркер владеет своим epoll-циклом (рекомендуется для NUMA).

Управление памятью – избегать частых динамических аллокаций (использовать пулы объектов, слейбы или, как минимум, std::pmr). Данные значения хранить как непрерывные блоки байтов.

Конфигурация – параметры (порт, максимальный размер кэша, политика вытеснения, число потоков) должны читаться из конфигурационного файла (например, JSON или TOML).

5. Технологический стек
Для C++:

Язык: C++17 (или C++20, на выбор)

Сеть: системные вызовы (socket, epoll, accept) либо обёртки (например, Boost.Asio – по желанию)

	Многопоточность: std::thread, std::jthread, синхронизация через std::mutex/std::shared_mutex или lock‑free структуры

Тестирование: Google Test для модульных тестов, нагрузочные утилиты wrk, hey, vegeta

Сборка: CMake

Для Rust (альтернатива):

Язык: Rust 2021

Runtime: Tokio (многопоточный)

Сеть: tokio::net::TcpListener / TcpStream

Кэш: DashMap для шардирования без блокировок, lru для политики

Тестирование: встроенные тесты, бенчмарки через criterion

Сборка: Cargo

6. План работ на неделю (примерное распределение)
День	Задачи
День 1	Изучение предметной области. Проектирование структур данных (классов/модулей). Написание архитектурной схемы. Согласование ТЗ.
День 2	Реализация ядра кэша – хеш‑таблица + двусвязный список (LRU) с защитой мьютексами (или шардирование). Написание юнит‑тестов для этих структур.
	День 3	Разработка сетевого уровня: создание TCP‑сервера с epoll, парсер команд, буферизация чтения/записи. Базовое логирование.
День 4	Интеграция кэша и сетевого слоя. Реализация всех команд (SET, GET, DELETE, EXISTS, TTL). Проверка сквозных сценариев.
День 5	Нагрузочное тестирование, профилировка (perf, Valgrind), оптимизация «узких» мест (уменьшение копирований, улучшение локализации).
День 6	Добавление команды STATS, метрик (количество операций, hit ratio, использование памяти). Настройка graceful shutdown.
День 7	Финальное тестирование, написание документации (README, описание протокола, примеры запуска), подготовка демонстрационного выступления.
7. Критерии приёмки (оценка преподавателем)
№	Критерий	Вес
1	Корректность реализации всех команд – SET, GET, DELETE, EXISTS (и TTL) работают согласно спецификации	25
	2	Производительность – достигнуто не менее 10 000 RPS на GET‑запросах (подтверждено бенчмарком)	25
3	Стабильность и масштабируемость – система выдерживает ≥ 1 000 одновременно открытых соединений без падений и утечек	20
4	Потокобезопасность – отсутствие гонок данных (проверено инструментами, например, ThreadSanitizer)	10
5	Управление памятью – нет утечек (Valgrind / AddressSanitizer), корректно отрабатывает LRU	10
6	Документация – наличие README, инструкции по сборке и примеров использования	5
7	Graceful shutdown – корректное завершение по сигналу, без потери данных (запись завершается)	5
8. Возможные расширения (для дополнительных баллов)
Персистентность – периодическое сохранение дампов кэша на диск и восстановление при старте.

	Репликация – синхронизация данных между несколькими экземплярами (master‑slave или кластер).

Шардирование по ключу (consistent hashing) для горизонтального масштабирования.

	Экспорт метрик в Prometheus или вывод их через HTTP‑эндпоинт.

Поддержка SSL/TLS для защищённого соединения.

Расширенный протокол (например, поддержка списков или хешей, как у Redis).