Files
beanstalkd/roadmap/00-overview.md
T
install b9bcb01322
Continous integration / Tests (push) Canceled after 0s
Testing clients / Build beanstalkd (push) Canceled after 0s
Continous integration / Docker build (push) Canceled after 0s
Testing clients / Test Pheanstalk PHP (push) Canceled after 0s
Testing clients / Test Greenstalk Python (3.9) (push) Canceled after 0s
Testing clients / Test Pystalk Python (3.10) (push) Canceled after 0s
Initialize
2026-10-15 10:52:58 +05:00

80 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Многопроцессный Beanstalkd
Статус: постановка на реализацию, код не реализован.
Дата фиксации: 2026-10-15.
База: исходники Beanstalkd 1.13 в этом каталоге.
## Цель
Позволить одному логическому серверу использовать несколько CPU-ядер для обработки независимых tubes, сохранив модель заданий Beanstalkd и динамический жизненный цикл очередей.
Принятое решение: процессы-владельцы групп tubes. У каждого владельца собственный event loop, задания, очереди, таймеры и WAL; сетевые frontend-процессы направляют операции владельцам через IPC. Supervisor обеспечивает эксклюзивность owner slots и управление жизненным циклом процессов.
```text
+-- owner slot 0: tubes, jobs, WAL
clients --> frontend(s) --IPC--+-- owner slot 1: tubes, jobs, WAL
+-- owner slot N: tubes, jobs, WAL
supervisor: topology, process generations, startup, shutdown, restart
```
## Границы Первого Этапа
- Один хост, статическая карта распределения, отдельный WAL каждого владельца.
- Каждый `reserve` / `reserve-with-timeout` работает с одной наблюдаемой tube. Настройка `watch target`, `ignore default` допускается.
- Связь tube с владельцем определяется по имени через фиксированные логические разделы. Постоянного каталога дескрипторов всех tubes нет.
- Consumer может держать несколько заданий. Его `use`, текущий watch list и ранее полученные резервации не обязаны относиться к одной tube или одному владельцу.
- Политика перехода от существующего однопроцессного сервера определяется в эпике 01. Рекомендуется opt-in с сохранением legacy, но обязательная поддержка двух режимов пока не утверждена.
- Полный end-to-end путь команд, восстановление, диагностика и проверки отказов входят в результат, а не откладываются после демонстрации `put`/`reserve`.
## Вне Объёма
- Межшардовый выбор задания из нескольких наблюдаемых tubes.
- Распараллеливание одной tube, глобальный FIFO между tubes.
- Динамическая миграция, автоматическая балансировка и изменение карты при работе сервера.
- Кластер между хостами, репликация и автоматическое назначение данных упавшего владельца другому slot.
- Shared-memory allocator, zero-copy и io_uring как предварительное условие реализации.
- Exactly-once выполнение пользовательского кода.
## Основные Инварианты
1. Имя tube всегда имеет одного владельца в пределах версии топологии, даже когда объект tube не существует.
2. Объект создаётся только владельцем и только по операции, которая предполагает создание по протоколу.
3. Два процесса не изменяют данные одного owner slot одновременно.
4. Переходы состояний job последовательны у владельца; права на reserved job принадлежат логической клиентской сессии.
5. Один reserve имеет не более одного результата; job имеет не более одной действующей резервации.
6. Очерёдность команд и ответов одного TCP-соединения сохраняется.
7. Сбой, недоступность и неизвестный результат не маскируются под успешную операцию или отсутствие задания.
8. Накопление IPC-запросов, ответов и тел ограничено памятью; медленный клиент не блокирует чужие очереди неограниченно.
9. Перезапуск с WAL использует ту же топологию и корректное пространство ID; несовпадение конфигурации обнаруживается до записи данных.
## Эпики И Зависимости
| ID | Постановка | Зависимости | Результат |
| --- | --- | --- | --- |
| 01 | [Контракты и baseline](01-contract.md) | Нет | Решения по внешнему поведению, отказам, ID и конфигурации |
| 02 | [Владение tubes](02-ownership.md) | 01 | Детерминированная маршрутизация и локальное создание |
| 03 | [IPC и сессии](03-ipc-sessions.md) | 01; интерфейсы 02 | Межпроцессный транспорт и безопасный жизненный цикл сессий |
| 04 | [Queue engine и протокол](04-queue-engine.md) | 02, 03 | Все операции над очередями через владельцев |
| 05 | [WAL и ID](05-persistence.md) | 01, 02; интеграция 03, 04 | Восстановление, уникальные ID, изоляция журналов |
| 06 | [Supervisor и эксплуатация](06-supervisor.md) | 02, 03; интеграция 04, 05 | Управляемый запуск, отказ и остановка процессов |
| 07 | [Приёмка и производительность](07-validation.md) | Baseline после 01; итог после 02-06 | Воспроизводимые функциональные и нагрузочные доказательства |
Порядок не запрещает совместную разработку согласованных интерфейсов. Минимальный запуск дочернего процесса для тестов можно сделать раньше эпика 06; это не означает готовность supervisor. Тесты пишутся в каждом эпике, а не только в конце.
## Общая Приёмка
- Все обязательные решения эпика 01 закрыты и документированы до реализации зависящего от них контракта.
- Исходные тесты используются как регрессионная база; отклонения допустимы только по согласованной матрице совместимости. Если выбран отдельный legacy-режим, он проходит прежний набор без ограничения multi-watch.
- Успешно проверены минимум два owner slots и несколько frontend-процессов, в том числе гонка создания одной tube через разные frontend.
- Протестированы job lifecycle, права сессий, таймеры, slow clients, аварии и WAL при одинаковых с baseline настройках durability.
- На независимых tubes подтверждён рост пропускной способности и реальная работа нескольких owner CPU; точный порог фиксируется после baseline, до финальных замеров.
- Для одной горячей tube ограничение последовательности явно показано в отчёте, а не скрыто агрегированной нагрузкой.
- Обновлены `README.md`, `doc/protocol.txt`, исходник руководства и эксплуатационные инструкции при реализации. Внешние ограничения и совместимость старых данных описаны явно.
## Основание
Текущий сервер последовательно выполняет `prottick`, `socknext` и callback в `serv.c:srvserve`. Реестры jobs/tubes и генератор ID глобальны. `process_queue` связывает job с `Conn*`, а WAL защищён от второго владельца. Поэтому разделение только listening socket или вызов `fork()` не дают корректного общего сервера.
Критический краткий контекст для последующей работы: [../AGENTS.md](../AGENTS.md).