Перейти к основному содержимому
Нормативная версия документации - английская

Эта страница переведена с английского языковой моделью. При любом расхождении верен английский оригинал.

Завершение

Чем ack, drop, retry и retry_after становятся в Kinesis, которая не подтверждает записи, а хранит одну контрольную точку на сегмент.

Отметка подтверждения на одном сегменте: контрольная точка стоит перед первой незавершённой доставкойОдин сегмент, записи в порядке поступления1готова2готова3идёт4готова5готова6идётКонтрольная точка: запись 2последняя запись передпервой выполняемойLeaseStore::checkpointесли аренда взятаКогда 3 завершится,контрольная точкасдвинется на 5:6 ещё выполняется
Схема текстом
  1. Контрольная точка: запись 2 последняя запись перед первой выполняемой → 2 готова: указывает
  2. Контрольная точка: запись 2 последняя запись перед первой выполняемой → LeaseStore ::checkpoint если аренда взята: записывает
  3. Один сегмент, записи в порядке поступления
  4. 1 готова
  5. 3 идёт
  6. 4 готова
  7. 5 готова
  8. 6 идёт
  9. Когда 3 завершится, контрольная точка сдвинется на 5: 6 ещё выполняется

Контрольная точка указывает на одну запись сегмента и означает, что все записи до неё обработаны. Поэтому крейт отслеживает доставки каждого сегмента в порядке поступления. Завершение помечает свою доставку обработанной, и контрольная точка сдвигается на последнюю запись непрерывного ряда обработанных доставок, который начинается с самой старой. Подтверждения из параллельных партиций воркеров приходят в любом порядке, а контрольная точка никогда не обгоняет запись, которая ещё выполняется. Завершение пишет в хранилище аренд, только когда сдвигает контрольную точку, и хранилище принимает запись, только пока этот экземпляр удерживает сегмент.

ИсходДействие на сегмент
ackОбработана: контрольная точка сдвигается, если ни одна более ранняя запись ещё не выполняется
dropОбработана, как при ack: контрольная точка проходит за отравленную запись
retry()Отказ (AckError::Unsupported) с предупреждением в журнале: запись остаётся необработанной и держит контрольную точку, а сегмент читается с неё заново, когда его аренду возьмут в следующий раз
retry() при max_attempts или потоке мёртвых писемКопия с номером попытки уходит в поток, а оригинал обработан
retry_after(delay)Копия с номером попытки уходит в поток, когда задержка истекла, а оригинал обработан
Предел исчерпанЗапись уходит в поток мёртвых писем, а без него обработана, и контрольная точка проходит за неё
Нет завершения до остановкиКонтрольная точка остаётся на месте, и следующий владелец сегмента прочитает запись снова

Сегмент читается по порядку, и Kinesis не умеет вернуть одну запись, поэтому возврат в очередь отвергается. Читатель идёт дальше, а запись возвращается после перезапуска или передачи аренды, вместе со всеми записями после неё. Гарантия доставки - at-least-once.

Перемотка заново начинает отметку подтверждения тех сегментов, которые она переносит. Завершение доставки, прочитанной до перемотки, ничего не меняет, поэтому запоздалый ack никогда не вернёт контрольную точку туда, откуда пришла перемотка. Закрытый сегмент помечается SHARD_END, только когда завершились все его доставки, и его дочерние сегменты начинают читаться после этого.

Повторы​

Повтор в Kinesis: предел попыток выбирает между копией в поток, потоком мёртвых писем и контрольной точкой за записьюЗаписьx-ruststream-retry-count говорит, какая это попыткаОбработчик возвращаетretry_after(delay) или retry() при объявленииmax_attempts: попытка ниже предела?Ниже предела:оригиналзавершается,копия уходитв потокНа пределе:запись уходитв потокмёртвых писемНа пределе,без мёртвых писем:контрольнаяточка проходитза неёКопия - новая запись в конце потока,в сегменте, который выбирает её ключОтложенную копию держит процесс:падение до срабатывания таймера её теряет
Схема текстом
  1. Запись x-ruststream-retry-count говорит, какая это попытка → Обработчик возвращает retry_after(delay) или retry() при объявлении: обработана
  2. Обработчик возвращает retry_after(delay) или retry() при объявлении → max_attempts: попытка ниже предела?: повтор
  3. max_attempts: попытка ниже предела? → Ниже предела: оригинал завершается, копия уходит в поток: ниже
  4. max_attempts: попытка ниже предела? → На пределе: запись уходит в поток мёртвых писем: на пределе
  5. max_attempts: попытка ниже предела? → На пределе, без мёртвых писем: контрольная точка проходит за неё
  6. Ниже предела: оригинал завершается, копия уходит в поток → Копия - новая запись в конце потока, в сегменте, который выбирает её ключ
  7. Отложенную копию держит процесс: падение до срабатывания таймера её теряет

Kinesis не придерживает записи и не считает доставки, поэтому и то и другое делает рантайм. Этим путём идут исход retry_after, а также retry() у регистрации, которая объявляет max_attempts или поток мёртвых писем dead_letter. Номер попытки хранится в заголовке копии x-ruststream-retry-count, и первая доставка считается первой попыткой.

Копия уходит в поток, который читает подписка, по адресу, который сообщает дескриптор KinesisStream, поэтому регистрация не называет адрес. Копия попадает в конец потока, в сегмент, который выбирает её ключ сегмента, за записями, записанными после оригинала. Поэтому повторённая запись теряет порядок относительно соседних. Если этот порядок важен, не объявляйте предел и позвольте retry() держать сегмент. Копию получает каждый потребитель потока, а не только тот, кто выполнил повтор.

Исчерпавшая попытки запись уходит в поток мёртвых писем вместе с полезной нагрузкой и заголовками. Предел без потока мёртвых писем снимает запись так же, как drop.