/mini-redis

Неполная идиоматичная реализация клиента и сервера Redis с помощью Tokio

Primary LanguageRustMIT LicenseMIT

Mini Redis

Оригинал

mini-redis - это неполная идиоматичная реализация клиента и сервера Redis с помощью Tokio.

Цель этого проекта - предоставить пример большого приложения, разработанного с помощью Tokio.

Дисклеймер Пожалуйста, не используйте mini-redis в продакшне. Этот проект является учебным ресурсом, в котором отсутствуют разные части протокола Redis, поскольку их реализация не представит новых концепций.

Почему Redis?

Основная цель этого проекта - изучение Tokio. Это требует проекта с широким набором возможностей с акцентом на простоте реализации. Redis, база данных, основанная на памяти, предоставляет широкий набор возможностей и использует простой сетевой протокол. Широкий набор возможностей позволяет продемонстрировать многие паттерны Tokio в контексте "реального мира".

Документацию сетевого протокола Redis можно найти здесь.

Набор команд, поддерживаемый Redis, можно найти здесь.

Запуск

Репозиторий предоставляет сервер, клиентскую библиотеку и некоторые клиентские исполняемые файлы для взаимодействия с сервером.

Команда для запуска сервера:

RUST_LOG=debug cargo run --bin mini-redis-server

Для предоставления структурированных логов используется крейт tracing.

Затем, в отдельном терминале, могут запускаться разные примеры клиентов, например:

cargo run --example hello_world

Кроме того, предоставляется клиент CLI для ручного запуска команд из терминала, например:

cargo run --bin mini-redis-cli set foo bar

cargo run --bin mini-redis-cli get foo

Поддерживаемые команды

mini-redis в настоящее время поддерживает следующие команды:

Спецификацию сетевого протокола Redis можно найти здесь.

Шаблоны Tokio

Проект демонстрирует несколько полезных шаблонов, включая:

Сервер TCP

server.rs запускает сервер TCP, который принимает соединения и создает новую задачу для каждого соединения. Он качественно обрабатывает ошибки accept.

Клиентская библиотека

client.rs показывает, как моделировать асинхронного клиента. Разные возможности предоставляются как async методы.

Состояние, распределяемое между сокетами

Сервер поддерживает экземпляр Db, который доступен всем соединениям. Экземпляр Db управляет состоянием "ключ-значение", а также возможностью "издатель/подписчик".

Кадрирование

connection.rs и frame.rs показывают идиоматичную реализацию сетевого протокола. Протокол моделируется с помощью промежуточного представления - структуры Frame. Connection принимает TcpStream и предоставляет API для отправки и получения значений Frame.

Мягкое завершение

Сервер реализует мягкое завершение. tokio::signal используется для регистрации SIGINT. После получения сигнала начинается завершение. Сервер перестает принимать соединения. Существующие соединения уведомляются о необходимости мягкого завершения. Выполняемая работа завершается и соединение закрывается.

Ограничение количества одновременных соединений

Сервер использует Semaphore для ограничения количества одновременных соединений. По достижении лимита сервер перестает принимать новые соединения до прекращения одного из существующих соединений.

Издатель/Подписчик

Сервер реализует нетривиальную возможность "издатель/подписчик". Клиент может подписываться на несколько каналов и обновлять подписку в любое время. Сервер реализует это с помощью широковещательного канала и StreamMap. Клиенты могут отправлять команды подписки на сервер для обновления активных подписок.

Использование std::sync::Mutex в асинхронном приложении

Сервер использует std::sync::Mutex, а не мьютекс Tokio для синхронизации доступа к общему состоянию. См. db.rs.

Тестирование асинхронного кода, зависящего от времени

В tests/server.rs находятся тесты для истечения времени жизни ключей. Эти тесты зависят от переданного времени. Для того, чтобы сделать тесты детерминистическими, используется фиктивное время с помощью утилит тестирования Tokio.

Лицензия

Этот проект находится под лицензией MIT.