Диск на порядки медленнее памяти, поэтому ядро держит прочитанные страницы файлов в оперативной памяти — это page cache. Под него идёт вся память, не занятая процессами; когда процессам нужно больше, кэш ужимается. Поэтому в free -h на долго работающем сервере колонка free маленькая, а available большая — паниковать не нужно.
Чтение. Первый read идёт на диск и заодно заполняет кэш; ядро ещё и читает наперёд (readahead), если доступ последовательный. Повторное чтение того же файла — копирование из памяти, на порядки быстрее. Отсюда эффект «холодного» и «прогретого» сервера после перезапуска.
Запись. write копирует данные в кэш, помечает страницы «грязными» и сразу возвращает управление. Сбросом на диск занимается ядро в фоне — через несколько секунд или при нехватке памяти. Это быстро, но если пропадёт питание или упадёт ядро, грязные страницы потеряются, хотя программа думала, что записала.
fsync. Вызов fsync(fd) ждёт, пока данные и метаданные файла дойдут до устройства. Именно его делают базы данных при коммите: транзакция считается подтверждённой, только когда запись в журнале (WAL) пережила бы сбой. fsync стоит от долей миллисекунды на SSD с конденсаторами до десятков миллисекунд на HDD, поэтому базы группируют коммиты (group commit), а настройки вроде synchronous_commit = off в PostgreSQL или acks/flush в брокерах — сознательный обмен надёжности на скорость.
Обход кэша. Базы, которые кэшируют данные сами (InnoDB, Oracle), часто открывают файлы с O_DIRECT, чтобы не держать два кэша. PostgreSQL, наоборот, опирается на page cache, поэтому shared_buffers ставят около четверти памяти. Kafka почти полностью полагается на page cache и последовательную запись.