Что такое zero-copy и почему 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
Подробно
Обычный путь read(file) → write(socket):
- DMA копирует данные с диска в page cache ядра;
readкопирует из page cache в буфер приложения (CPU);writeкопирует из буфера приложения в буфер сокета (CPU);- 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 работает для любых данных, включая шифруемые приложением.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✓sendfile отдаёт данные из page cache в сокет внутри ядра
- ✗Zero-copy означает, что данные вообще не читаются с диска, а берутся из сети
- ✗Kafka держит собственный кэш вместо page cache
- ✗Обычная отдача файла не требует копирований
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.