Эта страница переведена с английского языковой моделью. При любом расхождении верен английский оригинал.
Конвейеры обработки
Одна подписка держит в работе по захвату на каждого свободного воркера, в пределах размера пула
без одного соединения; workers_by_key(n) держит каждый ключ партиционирования на одном
конвейере.
Схема текстом
- Подписка InboxQueue, workers(4): по захвату в работе на каждого свободного воркера → Воркер 1 обработка и итог: захватывает
- Воркер 1 обработка и итог → Пул на 8: подписка держит до 7, одно остаётся для запросов обработчиков
- Подписка InboxQueue, workers(4): по захвату в работе на каждого свободного воркера → Воркер 2 обработка и итог
- Воркер 2 обработка и итог → Пул на 8: подписка держит до 7, одно остаётся для запросов обработчиков
- Подписка InboxQueue, workers(4): по захвату в работе на каждого свободного воркера → Воркер 3 обработка и итог
- Воркер 3 обработка и итог → Пул на 8: подписка держит до 7, одно остаётся для запросов обработчиков
- Подписка InboxQueue, workers(4): по захвату в работе на каждого свободного воркера → Воркер 4 обработка и итог
- Воркер 4 обработка и итог → Пул на 8: подписка держит до 7, одно остаётся для запросов обработчиков
- Один захват за раз: на SQLite, на таблице FIFO, на таблице со столбцом partition_key и на таблице аренды MySQL или MariaDB
- workers_by_key(n): строка идёт на конвейер своего partition_key, и ключ сохраняет порядок захвата
Рантайм опрашивает поток подписки по разу на каждого свободного воркера, и подписка одиночных доставок отвечает на каждый опрос захватом; подписка пакетов захватывает по пакету за раз. Подписка считает свои доставки в работе, так что наибольшее их число за раз говорит ей, сколько воркеров, и она держит захват в работе на каждого свободного. Захват рядом с другим начинается, только пока у пула есть лишнее соединение, и подписка никогда не держит больше, чем размер пула без одного: последнее соединение обслуживает собственные запросы обработчиков, их публикации и завершения, которым нужно соединение. Пул, которому не хватает места, выполняет меньше доставок за раз, а подписки на общем пуле оставляют друг другу место. После захвата, который ничего не взял, подписка захватывает по одному, пока захват снова не возьмёт строку, поэтому пустая таблица видит один захват на ожидание, а не по одному на воркера.
То, что держит доставка в работе, зависит от формы. В формах блокировки строк и рекомендательной
блокировки каждая доставка держит соединение до завершения, поэтому workers(n) держит до n
соединений. В форме аренды захват и завершение берут соединение только на свои операторы, а
подписка берёт одно раз в половину срока аренды, чтобы продлить свои аренды. В транзакционном
режиме каждая доставка держит соединение своей транзакции, в любой форме. Задайте размер пула с
учётом каждой подписки, которая держит соединения, ещё одного соединения для пула и соединений,
которые обработчики берут для своих запросов.
Некоторые таблицы держат в работе один захват за раз там, где одновременные захваты стоили бы
больше, чем дают. SQLite допускает одного писателя за раз, поэтому одновременные захваты только
сталкиваются. На таблице FIFO и на таблице со столбцом partition_key два одновременных захвата
могли бы закончиться не в порядке захвата. На MySQL и MariaDB захват аренды отмечает свои строки
в транзакции из нескольких операторов, которая до фиксации блокирует прочитанные строки, включая
аренды в работе. Воркеры по-прежнему работают параллельно; по очереди идут только захваты.
На SQLite захват аренды берёт одним оператором по строке на каждый воркер, которого видела подписка. Обработчик занятости SQLite не ставит писателя в очередь, если блокировка записи занята: он засыпает на миллисекунду или дольше и пробует снова. Захват одной строки на каждую доставку встречал бы подтверждения воркеров у блокировки записи на каждой доставке, и пока он спит, простаивали бы все воркеры. Строки сверх свободных воркеров ждут в подписке следующего свободного, уже внесённые в книгу аренд, поэтому их аренды продлеваются, пока они ждут, а остановленная подписка сразу возвращает их в очередь.
workers_by_key(n) запускает n конвейеров, и строка попадает на конвейер, на который указывает
хеш её partition_key. Строки одного ключа никогда не расходятся по двум конвейерам, поэтому
выполняются в порядке захвата. Группа FIFO идёт дальше: в работе одна строка группы за раз, во
всех брокерах и экземплярах, которые её читают, потому что захват берёт только голову группы, а
защита диалекта блокирует группу.
Обработчик, занятый вычислениями, работает на выделенных потоках через on_threads(n). Подписка
по-прежнему захватывает на рантайме приложения, а каждый поток выполняет запросы через
собственный небольшой пул, по умолчанию из одного соединения.
connection_limit удерживает пул сервиса и
соединения всех потоков в пределах того, что допускает база данных: подписка, которая превысила
бы этот предел, не запускается.
Две реплики сервиса на одной таблице делят её строки без координации: каждая захватывает сама, а форма захвата держит строку в одном месте за раз.