Files
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

9.4 KiB
Raw Permalink Blame History

Многопроцессный Beanstalkd

Статус: постановка на реализацию, код не реализован. Дата фиксации: 2026-10-15. База: исходники Beanstalkd 1.13 в этом каталоге.

Цель

Позволить одному логическому серверу использовать несколько CPU-ядер для обработки независимых tubes, сохранив модель заданий Beanstalkd и динамический жизненный цикл очередей.

Принятое решение: процессы-владельцы групп tubes. У каждого владельца собственный event loop, задания, очереди, таймеры и WAL; сетевые frontend-процессы направляют операции владельцам через IPC. Supervisor обеспечивает эксклюзивность owner slots и управление жизненным циклом процессов.

                              +-- 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 Нет Решения по внешнему поведению, отказам, ID и конфигурации
02 Владение tubes 01 Детерминированная маршрутизация и локальное создание
03 IPC и сессии 01; интерфейсы 02 Межпроцессный транспорт и безопасный жизненный цикл сессий
04 Queue engine и протокол 02, 03 Все операции над очередями через владельцев
05 WAL и ID 01, 02; интеграция 03, 04 Восстановление, уникальные ID, изоляция журналов
06 Supervisor и эксплуатация 02, 03; интеграция 04, 05 Управляемый запуск, отказ и остановка процессов
07 Приёмка и производительность 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.