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

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

Сегменты, разделение и слияние

Сегмент обеспечивает фиксированную долю пропускной способности потока. Разделение или слияние закрывает сегменты и открывает дочерние, которые читаются после родительских.

Разделение превращает сегмент 0 в сегменты 1 и 2, слияние превращает сегменты 1 и 2 в сегмент 3, и каждый дочерний читается после родительскихСегмент 0, закрытконечный порядковый номерСегмент 1, закрытнижняя половина 0Сегмент 2, закрытверхняя половина 0Сегмент 3, открытродители 1 и 2Дочерний сегмент читается, только когда каждый родитель прочитан до конца,поэтому записи одного ключа сохраняют порядокпри изменении
Схема текстом
  1. Сегмент 0, закрыт конечный порядковый номер → Сегмент 1, закрыт нижняя половина 0: разделение
  2. Сегмент 0, закрыт конечный порядковый номер → Сегмент 2, закрыт верхняя половина 0: разделение
  3. Сегмент 1, закрыт нижняя половина 0 → Сегмент 3, открыт родители 1 и 2: слияние
  4. Сегмент 2, закрыт верхняя половина 0 → Сегмент 3, открыт родители 1 и 2: слияние
  5. Дочерний сегмент читается, только когда каждый родитель прочитан до конца, поэтому записи одного ключа сохраняют порядок при изменении

Каждый сегмент принимает на запись до 1 МБ или 1000 записей в секунду. На чтение он отдаёт до 2 МБ в секунду и не больше пяти вызовов GetRecords в секунду. Эти пять вызовов делят все потребители, которые читают сегмент, поэтому этот предел - не про оплату: он определяет, как часто сегмент вообще можно прочитать. У потока в режиме выделенной ёмкости столько сегментов, сколько ему задали, а поток в режиме по запросу получает столько, сколько нужно его трафику.

Разделение делит диапазон хеш-ключей одного сегмента между двумя дочерними. Слияние объединяет два соседних сегмента в один. В обоих случаях родительские сегменты закрываются: ListShards сообщает для них конечный порядковый номер, новых записей они не принимают, а имеющиеся хранят, пока не истечёт срок хранения. Читатель, дошедший до конца закрытого сегмента, не получает следующего итератора: это SHARD_END.

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

Подписка заново перечисляет сегменты каждые 10 секунд, поэтому дочерний сегмент открывается в течение этого времени после того, как его родители прочитаны. Читатель дочернего сегмента продолжает с его контрольной точки, как показывает страница Чтение. Дочерний сегмент без контрольной точки открывается с самой старой записи, поэтому то, что в него записали до запуска читателя, тоже прочитывается. create_if_missing(shards) создаёт отсутствующий поток в режиме выделенной ёмкости с заданным числом сегментов и ждёт до минуты, пока он не станет доступен.

Эта модель взята у самого Amazon Kinesis Data Streams (квоты и ограничения, режимы ёмкости, разделение и слияние, чтение после разделения и слияния).