Получить доступ

Что такое zero-copy и почему Kafka так быстро отдаёт данные?

SeniorСеть и ввод-выводKafka
Ещё спрашивают так:
  • Как работает sendfile?
  • Почему Kafka быстрая?
  • Сколько раз копируются данные при отдаче файла по сети?
Коротко

Обычная отдача файла: диск → page cache → буфер приложения → буфер сокета → сеть: 4 копирования и 4 переключения режима. sendfile передаёт данные из page cache в сокет внутри ядра — приложение их не трогает.

  • Экономит копирования, CPU и кэши процессора; полезно для статики, Kafka, прокси
  • Kafka: последовательная запись в лог, page cache вместо своего кэша, sendfile потребителям, пакеты и сжатие
  • Не работает, если данные надо менять по пути — например, TLS в пространстве пользователя (помогает kTLS)

А ещё Другие приёмы: mmap, splice, MSG_ZEROCOPY, io_uring, RDMA

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Подробно

Обычный путь read(file) → write(socket):

  1. DMA копирует данные с диска в page cache ядра;
  2. read копирует из page cache в буфер приложения (CPU);
  3. write копирует из буфера приложения в буфер сокета (CPU);
  4. DMA копирует из буфера сокета в сетевую карту.

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

sendfile(socket, file, offset, count) — ядро передаёт данные из page cache прямо в сокет. С поддержкой сетевой карты (scatter-gather DMA) не копирует даже в буфер сокета — только дескрипторы. Итог: нет копирований через CPU в пространство пользователя, один системный вызов, кэши процессора не засоряются. Используется в nginx (sendfile on), Kafka, FileChannel.transferTo в Java, os.sendfile в Python.

Почему Kafka быстрая — набор решений вокруг этого:

  • журнал с последовательной записью — только дописывание в конец файла сегмента; последовательный доступ быстр и на HDD, и на SSD;
  • page cache вместо собственного кэша — свежие сообщения обычно читаются из памяти ядра; нет двойного кэширования и пауз GC от кэша в куче JVM;
  • zero-copy — сообщения хранятся на диске в том же формате, что идут по сети, поэтому брокер отдаёт их потребителю через sendfile, не разбирая;
  • пакеты — продюсер копит сообщения (linger.ms, batch.size), сжимает пачку целиком, брокер пишет её как есть;
  • партиции — параллелизм по брокерам и потребителям.

Ограничения zero-copy:

  • данные нельзя менять по пути: если брокер должен перекодировать формат для старого клиента — копирование возвращается;
  • TLS шифрует в пространстве пользователя — sendfile неприменим, пока не включён kTLS (шифрование в ядре);
  • выгода видна на больших объёмах; для мелких ответов важнее число системных вызовов.

Родственные механизмы: mmap (файл как память, без копии при чтении), splice/tee (перекладка между дескрипторами через канал), MSG_ZEROCOPY для отправки из пользовательских буферов, io_uring с зарегистрированными буферами, RDMA между машинами.

Пример

// Отдать файл в сокет без копирования через JVM
try (FileChannel file = FileChannel.open(path, StandardOpenOption.READ)) {
    long pos = 0, size = file.size();
    while (pos < size) pos += file.transferTo(pos, size - pos, socketChannel);  // sendfile внутри
}

Что хотят услышать

  • Обычный путь данных с копированиями и переключениями.
  • Как sendfile убирает копии, роль page cache и DMA.
  • Набор причин скорости Kafka, а не только zero-copy.
  • Ограничения: изменение данных, TLS.

Частые ошибки

  • Объяснять скорость Kafka одним словом «zero-copy».
  • Считать, что zero-copy работает для любых данных, включая шифруемые приложением.

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем