Вдохновившись проектом, где сделали интерактивную карту внутреннего устройства Postgres (писал о нём тут), я решил собрать похожую карту для Redis: poltora.dev/redis.
Это не просто статичная схема. По карте можно перемещаться, открывать встроенную консоль, запускать команды и смотреть их выполнение шаг за шагом: от сокета и RESP-парсера до поиска ключа, аллокации памяти, формирования ответа и записи AOF или RDB.
Что именно показывает карта
В центре находится модель одного экземпляра Redis. Команда начинается у клиента, попадает в буфер соединения, разбирается RESP-парсером, проходит проверку команды и выполняется в основном потоке. После этого карта отдельно показывает работу с keyspace, объектом и его представлением в памяти, очередь ответа клиенту и, для изменяющих команд, путь данных в AOF.
Сейчас модель понимает основные операции со строками, хешами, списками, множествами, sorted set и streams. Например, можно выполнить SET, GET, DEL, HSET, HGETALL, LPUSH, LRANGE, SADD, ZRANGE, XADD, EXPIRE, TTL, MEMORY USAGE и BGSAVE. Полный список доступен по команде HELP во встроенной консоли.
Для нескольких сценариев есть готовые эксперименты. Они позволяют сравнить короткую и длинную строку, увидеть смену внутреннего encoding у структуры, проследить истечение TTL, создать давление на maxmemory, запустить BGSAVE и посмотреть copy-on-write, когда родительский процесс изменяет данные во время создания снимка.
Откуда взялась модель
Карта основана на разборе исходного кода Redis 8.10.1. Маршрут обычной команды реконструирован по networking.c, server.c, db.c, kvstore.c, dict.c и реализации конкретных типов данных. Для AOF отдельно прослежен путь от буфера server.aof_buf через системный write() в page cache ядра и затем на постоянное хранилище. Для RDB показан отдельный процесс BGSAVE, который сначала разделяет физические страницы памяти с родителем, а затем получает собственные страницы при записи благодаря copy-on-write.
Из-за этого на карте намеренно нет выдуманной «общей очереди команд» или отдельного сервиса для каждого шага. У каждого клиента есть собственный входной буфер и список подготовленных команд, но выполнение команд сходится в основном потоке. Обычный GET читает объект из памяти и не обращается к AOF, RDB или диску.
Память — это не только размер значения
Одна из целей проекта — показать, почему размер payload и потребление памяти процессом Redis не совпадают. Модель разделяет полезные данные, запрос аллокатору, size class, страницы аллокатора, резидентную память процесса и файловый page cache ядра.
Удаление ключа освобождает слот, но не обязательно немедленно возвращает физическую страницу операционной системе. Несколько объектов могут разделять одну страницу аллокатора, и она остаётся резидентной, пока на ней есть занятые участки. Поэтому после DEL логический объём данных уменьшается сразу, а RSS может остаться прежним. В эксперименте с очисткой памяти это видно отдельно.
Что является упрощением
Redis City — образовательная модель, а не запущенный бинарник Redis, эмулятор jemalloc или профилировщик. Длины UTF-8 строк вычисляются, но накладные расходы объектов, size classes, размещение по страницам и длительность операций являются приближениями. Базовый RSS задан как допущение и не измеряет память компьютера посетителя.
Визуальное расположение блоков также не является физической картой адресов. Оно показывает связи между подсистемами. Например, верхний слой с объектами — семантическое представление keyspace, нижний слой — модель резидентных страниц, а page cache AOF и RDB принадлежит ядру ОС, а не heap процесса Redis.
Кластер, репликация, Sentinel, Lua/functions, Pub/Sub, транзакции и модули пока не входят в модель. Это сознательное ограничение: если показать все подсистемы одновременно, обычный путь SET или GET перестанет читаться.
Как всё запускается
Симулятор целиком работает в браузере. Он не подключается к живому Redis, не запрашивает пароль и ничего не меняет на сервере. Модель команд написана на TypeScript, сцена собрана процедурно на Three.js, а сборка публикуется как статические HTML, CSS и JavaScript. На production не нужен отдельный Node.js-процесс, Redis или база данных для самой карты.
Команда вычисляется один раз, после чего интерфейс показывает результат через последовательность контрольных точек: DB, allocation, TTL, journal и durability. Повторное воспроизведение анимации восстанавливает состояние до команды и не исполняет её второй раз.
Как попробовать
Откройте Redis City, затем раскройте Console и начните с простого сценария:
SET city "Hello Redis"
GET city
DEL cityПосле этого попробуйте SET temporary hello EX 6, проследите TTL и выполните GET temporary после истечения модельного времени. Для более сложного сценария запустите BGSAVE, а во время создания снимка измените существующий ключ — карта покажет, какая страница отделилась по copy-on-write.
Проект остаётся моделью, поэтому его главная задача — не дать точные показатели производительности, а сделать невидимые переходы Redis наблюдаемыми и отделить реальное поведение от распространённых упрощений.
