Файберы, потоки и многозадачность¶
Общие сведения¶
Данный раздел содержит описание модели кооперативной многозадачности в Picodata. Эти сведения помогут разработчикам создавать расширения для Picodata на языке Rust.
См. также:
- Tarantool internals — Fibers
- Tarantool — Fibers, yields, and cooperative multitasking
- Tarantool — C API Reference — Module fiber
Файберы и устройство потоков¶
Внутри основного процесса picodata
существует несколько потоков ОС:
tx thread
— основной поток для выполнения SQL-команд и в целом логики, связанной с действиями пользователя.tx thread
большую часть времени выполняется на одном и том же ядре ЦП, редко совершает операции ввода/вывода (I/O) и, соответственно, реже привлекает внимание планировщика ОС- некоторое количество вспомогательных потоков (например, WAL, поток репликации и т.д.), в большей степени связанных с операциями ввода/вывода накопителя или сети
Понятие файбера относится к реализации кооперативной многозадачности в Picodata, т.е. к возможности выполнять асинхронно несколько операций внутри одного потока ОС.
Файберы — наборы инструкций, которые также называются легковесными
потоками, выполняющимися внутри tx thread
и остальных потоков.
Активность в СУБД происходит в виде сменяющих друг друга файберов,
которые выполняются асинхронно и под управлением внутреннего
планировщика Picodata:
Все события внутри tx thread
основаны не неблокирующих системных
вызовах, за которыми следит libev
. Таким образом, в рамках tx
thread
, Picodata является однопоточной СУБД с собственным легковесным
планировщиком. Это обеспечивает лучшую управляемость и решает проблемы,
связанные с распределенной природой СУБД.
Каждый файбер исполняет определенный набор инструкций. Как правило, это отдельная полезная функция, например установка сетевого подключения, исполнение пользовательской SQL-команды и т.д. Выполнив свою функцию, файбер инициирует событие переключения — и в этот момент меняет свое состояние.
Состояния файбера¶
Любой запущенный файбер может быть в одном из следующих состояний:
- running — исполняется
- suspended — приостановлен в ожидании какого-то события
- ready — готов продолжить работу
- dead — завершен
В каждый момент времени в состоянии running может находиться не более 1 файбера.
Жизненный цикл файбера¶
Процесс исполнения кода с учетом передачи управления между файберами показан на схеме ниже.
Переключения (yields)¶
Переключением мы называем особое событие в контексте кооперативной многозадачности, при котором управление внутри потока переходит от одного файбера к другому (последний должен быть в состоянии ready).
Передача управления между файберами¶
Инициатором переключения всегда выступает сам файбер, в коде которого для этого происходит вызов соответствующей функции. В этот момент текущий файбер изменяет свое состояние на suspended или ready, а следующий файбер переходит из состояния ready в состояние running.
При передаче управления используется первым в очереди файбер в состоянии ready. Если очередь из таких файберов заканчивается, управление возвращается циклу событий (event loop).
Избегание блокировок переключения и голодания¶
Если файбер не передает управление другим файберам в течение долгого времени, это приводит к голоданию (starvation) остальных файберов. Они не смогут продолжить работу и вызовут увеличение latency вплоть до полного зависания инстанса. Гарантированно выйти из ситуации зависания можно путем перезагрузки инстанса.