Эта страница переведена с английского языковой моделью. При любом расхождении верен английский оригинал.
Завершение
Чем ack, drop, retry и retry_after становятся в Kinesis, которая не подтверждает записи, а
хранит одну контрольную точку на сегмент.
Схема текстом
- Контрольная точка: запись 2 последняя запись перед первой выполняемой → 2 готова: указывает
- Контрольная точка: запись 2 последняя запись перед первой выполняемой → LeaseStore ::checkpoint если аренда взята: записывает
- Один сегмент, записи в порядке поступления
- 1 готова
- 3 идёт
- 4 готова
- 5 готова
- 6 идёт
- Когда 3 завершится, контрольная точка сдвинется на 5: 6 ещё выполняется
Контрольная точка указывает на одну запись сегмента и означает, что все записи до неё обработаны. Поэтому крейт отслеживает доставки каждого сегмента в порядке поступления. Завершение помечает свою доставку обработанной, и контрольная точка сдвигается на последнюю запись непрерывного ряда обработанных доставок, который начинается с самой старой. Подтверждения из параллельных партиций воркеров приходят в любом порядке, а контрольная точка никогда не обгоняет запись, которая ещё выполняется. Завершение пишет в хранилище аренд, только когда сдвигает контрольную точку, и хранилище принимает запись, только пока этот экземпляр удерживает сегмент.
| Исход | Действие на сегмент |
|---|---|
ack | Обработана: контрольная точка сдвигается, если ни одна более ранняя запись ещё не выполняется |
drop | Обработана, как при ack: контрольная точка проходит за отравленную запись |
retry() | Отказ (AckError::Unsupported) с предупреждением в журнале: запись остаётся необработанной и держит контрольную точку, а сегмент читается с неё заново, когда его аренду возьмут в следующий раз |
retry() при max_attempts или потоке мёртвых писем | Копия с номером попытки уходит в поток, а оригинал обработан |
retry_after(delay) | Копия с номером попытки уходит в поток, когда задержка истекла, а оригинал обработан |
| Предел исчерпан | Запись уходит в поток мёртвых писем, а без него обработана, и контрольная точка проходит за неё |
| Нет завершения до остановки | Контрольная точка остаётся на месте, и следующий владелец сегмента прочитает запись снова |
Сегмент читается по порядку, и Kinesis не умеет вернуть одну запись, поэтому возврат в очередь отвергается. Читатель идёт дальше, а запись возвращается после перезапуска или передачи аренды, вместе со всеми записями после неё. Гарантия доставки - at-least-once.
Перемотка заново начинает отметку подтверждения тех сегментов, которые она
переносит. Завершение доставки, прочитанной до перемотки, ничего не меняет, поэтому запоздалый
ack никогда не вернёт контрольную точку туда, откуда пришла перемотка. Закрытый сегмент
помечается SHARD_END, только когда завершились все его доставки, и его дочерние сегменты
начинают читаться после этого.
Повторы
Схема текстом
- Запись x-ruststream-retry-count говорит, какая это попытка → Обработчик возвращает retry_after(delay) или retry() при объявлении: обработана
- Обработчик возвращает retry_after(delay) или retry() при объявлении → max_attempts: попытка ниже предела?: повтор
- max_attempts: попытка ниже предела? → Ниже предела: оригинал завершается, копия уходит в поток: ниже
- max_attempts: попытка ниже предела? → На пределе: запись уходит в поток мёртвых писем: на пределе
- max_attempts: попытка ниже предела? → На пределе, без мёртвых писем: контрольная точка проходит за неё
- Ниже предела: оригинал завершается, копия уходит в поток → Копия - новая запись в конце потока, в сегменте, который выбирает её ключ
- Отложенную копию держит процесс: падение до срабатывания таймера её теряет
Kinesis не придерживает записи и не считает доставки, поэтому и то и другое делает рантайм. Этим
путём идут исход retry_after, а также retry() у регистрации, которая объявляет
max_attempts или поток мёртвых писем
dead_letter. Номер попытки хранится в
заголовке копии x-ruststream-retry-count, и первая доставка считается первой попыткой.
Копия уходит в поток, который читает подписка, по адресу, который сообщает дескриптор
KinesisStream, поэтому регистрация не называет адрес.
Копия попадает в конец потока, в сегмент, который выбирает её ключ сегмента, за записями,
записанными после оригинала. Поэтому повторённая запись теряет порядок относительно соседних.
Если этот порядок важен, не объявляйте предел и позвольте retry() держать сегмент. Копию получает
каждый потребитель потока, а не только тот, кто выполнил повтор.
Исчерпавшая попытки запись уходит в поток мёртвых писем вместе с полезной нагрузкой и заголовками.
Предел без потока мёртвых писем снимает запись так же, как drop.