Эта страница переведена с английского языковой моделью. При любом расхождении верен английский оригинал.
Окно
Подписка с конвейером завершает доставки в окне: доставки одного чтения ставят свои побочные эффекты в очередь, и один сброс отправляет их вместе с завершениями.
Схема текстом
- Один сброс, один обмен: INCR для 1-0; INCR для 3-0; XACK 1-0 2-0 3-0
- Запись 1-0 INCR в очередь → ack: сегмент сохранён
- ack: сегмент сохранён → INCR для 1-0
- Запись 2-0 INCR в очередь → drop: сегмент отброшен
- drop: сегмент отброшен → XACK 1-0 2-0 3-0: лишь XACK
- Запись 3-0 INCR в очередь → ack: сегмент сохранён
- ack: сегмент сохранён → INCR для 3-0
- При .atomic() каждый сегмент - MULTI, его команды, завершение своей доставки, затем EXEC
.pipeline() в точке
монтирования открывает окно над подпиской. Каждая доставка одного чтения занимает в нём ячейку.
Команды, которые её обработчик ставит в очередь через Ctx<keys::Pipeline>, попадают в сегмент
ячейки: конвейер fred, открытый при первой такой команде. Ответа на команду обработчик не видит.
Исход решает судьбу сегмента: ack сохраняет его, а drop, retry и retry_after
отбрасывают. Каждый исход отправляет то же завершение, что и без окна. Доставка, которую удалили,
не завершив, завершения не отправляет: её сегмент отбрасывается, а запись остаётся
неподтверждённой.
Окно сбрасывается, когда число завершённых доставок достигает COUNT чтения, когда незавершённых
доставок не осталось или когда подписка останавливается. Сброс отправляет сохранённые сегменты в
порядке их фиксации, а затем завершения этого чтения, одним конвейером через соединение пула.
Завершения потока уходят одной командой XACK, а завершения надёжного списка - по одной LREM на
запись. Под нагрузкой это один обмен с сервером на чтение.
.atomic() заключает каждый сегмент
в MULTI и EXEC и помещает внутрь завершение самой доставки. Тогда побочные эффекты обработчика
и его подтверждение вступают в силу вместе. Отката в Redis нет: команда, которая вернула ошибку
внутри EXEC, оставляет остальные выполненными
(транзакции). В кластере
все ключи сегмента должны находиться в слоте ключа подписки.
Если сброс возвращает ошибку, поток доставок выдаёт её один раз. В формах с завершением запись, завершение которой не удалось, остаётся неподтверждённой и доставляется повторно.