Сейчас память можно увеличить ползунком, Redis поднять одной командой, а состояние сервера оценить по строке в панели управления. Но за этим удобством стоит история компромиссов — сначала инженерам пришлось научить компьютеры работать так, будто памяти больше, чем есть на самом деле, потом диски собрали в массивы, горячие данные перенесли в Redis, а всю эту сложность спрятали за и managed-сервисами.
Индустрия десятилетиями строила убедительные иллюзии поверх ограниченной физической реальности, но почему-то памяти до сих пор недостаточно. Почему? Разобрал в статье.
Виртуальная память как великое инженерное мошенничество
Есть старый инженерный фокус, на котором держится почти вся современная вычислительная техника, — компьютеру показывают ресурс, которого у него на самом деле нет… Да, это про виртуальную память, которая в каком-то смысле стала первой успешной инфраструктурной иллюзией задолго до облаков и SaaS-моделей. Современная инфраструктура даёт похожее ощущение бесконечного пространства, пока где-то в отдалённом ЦОД сисадмин, нервно закуривая сигарету, смотрит на графики загрузки.
Но чтобы понять, насколько странной была сама идея виртуальной памяти, нужно ненадолго вернуться в начало 1950-х. В то время машины могли занимать целые комнаты, потреблять электричество как небольшой район и при этом вести себя крайне обидчиво по отношению к программистам, которые осмеливались попросить у них слишком много памяти под свои задачи.
Большинству разработчиков сейчас в принципе тяжело представить, насколько физическим было программирование тех лет. Сейчас мы запускаем контейнеры, поднимаем ВМ, раздаём Kubernetes-манифесты и обсуждаем задержки так, словно речь идёт о погоде. В конце 1950-х программист заранее решал, какой кусок программы должен находиться в памяти прямо сейчас, а какой можно временно убрать во внешнее хранилище. И если в этом планировании что-то шло не так, машина останавливалась.
Тяжелее всего было вычислительным центрам — компьютеры обслуживали несколько задач одновременно, пользователей становилось больше, программы росли, а нехватка памяти сохранялась. Старый подход посыпался на масштабе, как Галактическая Империя Азимова, которая казалась вечной до тех пор, пока Селдон не увидел в её размере будущий крах.
В поисках решения проблемы в Манчестерском университете начали разрабатывать Atlas — компьютер, который потом войдёт в историю как одна из первых машин с виртуальной памятью. Проектом руководил Том Килберн, который в 1948 году участвовал в создании Manchester Baby. Он выбрал для него архитектуру регистрового уровня и набор инструкций, а также написал программу, которая впервые успешно запустилась на компьютере с архитектурой stored-program. Так вычислительная техника подошла к тому, что Тьюринг описывал ещё в 1930-х — инструкции и данные живут в одной памяти, а машина может менять ход работы.
Atlas
Если Манчестерский малыш показал, что программу можно хранить вместе с данными, то Atlas научился скрывать от неё ограниченность памяти. Приложение видело только адресное пространство, а система сама решала, где будут лежать нужные данные. Здесь впервые проявилась та логика, которую индустрия потом будет воспроизводить десятилетиями — если ресурса не хватает физически, нужно создать архитектуру, которая сделает нехватку менее заметной.
Позже эту идею развила IBM в System/360, где появился механизм Dynamic Address Translation. Он переводил адреса, с которыми работала программа, в физические адреса памяти через таблицы страниц и сегментов. Именно отсюда позже вырастет современная виртуализация, многозадачность и вообще вся привычная для нас вычислительная среда.
IBM System/360
Правда, как и любая хорошая иллюзия, виртуальная память была прекрасна, пока нагрузка оставалась в разумных пределах. Когда памяти переставало хватать, система начинала метаться между RAM и внешним хранилищем, бесконечно перетаскивая страницы туда-сюда. Позже это состояние назовут thrashing (пробуксовка) — очень ироничный термин, кстати.
Когда диски начали притворяться надёжными
К концу 1980 года компьютеры научились обрабатывать серьёзные объёмы данных, корпоративные системы начали жить не отдельными файлами, а целыми массивами информации, и выяснилась неприятная вещь — диски-то ломаются. Нужно было что-то делать.
В 1987 году исследователи из Калифорнийского университета в Беркли (признан нежелательным на территории РФ) публикуют работу с названием «A Case for Redundant Arrays of Inexpensive Disks». Интересно, что изначально речь шла именно об inexpensive disks (недорогих дисках), а уже позже индустрия аккуратно заменит это слово на independent (независимых дисков), чтобы звучало взрослее и не так напоминало признание в экономии.
Смысл статьи был простым: зачем покупать один большой диск, если можно взять много маленьких, правильно распределить между ними данные и получить систему, которая в ряде сценариев окажется быстрее, дешевле и надёжнее. В этом был тот самый дух инженерной ереси, который потом ещё не раз спасёт индустрию.
В RAID описали несколько способов договориться с ненадёжностью дисков. Самый простой вариант, RAID 0, разбивал данные на полосы и раскладывал их по нескольким накопителям. Эта схема называется «чередованием» и даёт хороший прирост скорости, потому что чтение и запись идут параллельно. Один диск хранит один фрагмент, второй — другой, третий — следующий, и вместе они работают бодрее, чем один накопитель в одиночестве. Правда, стоит умереть одному диску, и весь массив превращается в красивую, но бесполезную археологическую находку.
Сравнение RAID
На основе другой логики появился RAID 1, где данные отзеркаливаются на второй диск. Один накопитель хранит копию другого, администратор спит чуть крепче, но полезный объём хранения сразу уменьшается вдвое.
Дальше начинается самая красивая часть этой истории. Вместо того чтобы полностью дублировать данные, инженеры решают хранить дополнительную информацию, по которой потерянный фрагмент восстанавливается при отказе одного накопителя. Так появился RAID 5. Долгое время он выглядел почти идеальным компромиссом между ценой, скоростью и надёжностью. Однако во время восстановления RAID-массив должен прочитать огромный объём данных с оставшихся дисков, чтобы пересобрать потерянное. Чем больше накопители, тем дольше длится восстановление и тем выше шанс, что в процессе всплывёт URE.
RAID 6 добавил возможность пережить отказ двух дисков, но за это пришлось платить вычислениями чётности, сложностью и производительностью записи.
Впрочем, вся история хранения данных состоит из таких обменов. Хотите быстрее — будет рискованнее, хотите надёжнее — будет дороже, хотите и быстрее, и надёжнее, и дешевле — добро пожаловать в раздел фантастики, третья полка справа, рядом со Стругацкими.
Потом появились гибридные уровни RAID, где инженеры стали комбинировать уже не отдельные диски, а целые массивы:
RAID 10 — чередование поверх зеркал (RAID 0, собранный из пар RAID 1). В этом случае данные читаются и пишутся быстрее, а система может спокойно пережить отказ одного диска в каждой паре.
RAID 50 строит чередование поверх групп RAID 5, а RAID 60 делает то же самое с группами RAID 6, получая больше устойчивости к отказам ценой сложности, ёмкости и вычислений чётности.
RAID 1E расширяет идею зеркалирования на массивы с нечётным кол-вом дисков. Данные и их копии распределяются по разным накопителям, поэтому система получает отказоустойчивость.
Так RAID изменил саму философию надёжности — отдельные диски могут ломаться. Это нормально, если архитектура заранее знает, что с этим делать.
Как память стала отдельным инфраструктурным слоем
Интересно, что каждое поколение разработчиков торжественно объявляет, что памяти теперь много, SSD летают, облака бесконечны, и вообще человечество победило инфраструктурные ограничения. А потом кто-нибудь открывает Grafana, видит задержки и осознаёт, что физика всё ещё существует.
К началу 2000-х интернет перестал быть местом, где люди выкладывали фотографии котиков на HTML-странички… Появились соцсети, поисковики, маркетплейсы, стриминг и огромные веб-приложения. Пользователь нажимает кнопку, обновляет страницу, ставит лайк, пишет комментарий, открывает уведомления, а сервер в этот момент получает сотни запросов к базе данных.
Но даже очень хорошая база данных плохо переносит повышенные нагрузки. Особенно это чувствовалось в эпоху ранних форумов и CMS, где одна страница могла запускать десятки SQL-запросов подряд. Тогда индустрия снова посмотрела на оперативную память — только уже не как на временное пространство для вычислений, а как на место, где данные могут жить постоянно.
Сначала проблему решали локально. Например, в 2003 году Брэд Фицпатрик для снижения нагрузки на LiveJournal написал Memcached — систему кэширования, которая хранила часто используемые данные в оперативной памяти. А потом… в 2009 году появился Redis.
Вместо тяжёлой распределённой системы Сальваторе Санфилиппо предложил вызывающе простой инструмент. Один основной процесс, однопоточная обработка команд, данные в оперативной памяти и короткий путь выполнения, где скорость рождается не из сложности, а из её отсутствия.
Redis сделал доступ к «горячим данным» быстрым и предсказуемым. Приложение смогло держать рядом с собой сессии, счётчики, результаты тяжёлых запросов и другое короткоживущее состояние, за которым слишком дорого каждый раз ходить в основную базу. За счёт этого интерфейс стал отвечать быстрее, счётчики обновлялись почти сразу, а пользователь не успевал заметить задержки.
Проблема в том, что вместе с Redis индустрия приобрела новую вредную привычку — если раньше разработчики пытались «лечить» всё базой данных, то теперь они начали лечить всё памятью. Медленный запрос? Redis. Сложная архитектура? Redis. Плохо написанный backend? Redis. Так кэш начал превращаться из ускорителя в пластырь поверх системных проблем.
Но не Redis единым…
Вокруг Redis постепенно вырос целый отдельный мир систем, где каждая решает свой класс задач:
Memcached — уже знакомый вам ветеран интернета, который до сих пор прекрасно живёт. Это стабильно быстрый распределённый кэш для хранения горячих данных и снижения нагрузки на базы данных.
DragonflyDB — хранилище, которое появилось как попытка решить одну из старых проблем Redis — однопоточную архитектуру. Система умеет эффективно использовать много ядер и хорошо чувствует себя на современных VPS и облачных инстансах с десятками vCPU. Особенно полезен там, где Redis начинает упираться в CPU под высокой нагрузкой.
KeyDB — высокопроизводительная версия Redis. Здесь уже есть полноценная многопоточность и активная репликация.
Valkey — продолжение опенсорсной ветки Redis после изменений лицензии Redis Inc.
Hazelcast — платформа для работы с данными в реальном времени, где память от нескольких серверов собирается в общий распределённый слой. Её часто используют в крупных Java-системах, когда нужно не просто держать часто запрашиваемые данные ближе к приложению, а распределять состояние между узлами и работать с ним, как с единой логической структурой.
Apache Ignite — тяжёлая инженерная платформа с SQL поверх памяти, распределёнными вычислениями и обработкой данных в реальном времени. Особенно хорошо она чувствует себя там, где нужно быстро работать с большими объёмами данных.
Aerospike — очень интересная гибридная система между памятью и storage. Aerospike хранит индексы в RAM, а сами данные может держать на SSD. Получается архитектура, где память становится не складом данных, а системой навигации по ним. Особенно хорошо это работает в adtech, антифроде, recommendation engines и realtime bidding, где главное — максимально быстро находить нужное среди гигантских массивов информации.
Caffeine — один из самых сильных локальных кэшей для JVM. Подходит для сценариев, где частые данные можно держать прямо в памяти приложения.
На основе этого, идеальной памяти не существует. Есть только компромисс между задержкой, стоимостью, надёжностью, сложностью эксплуатации и психологическим состоянием инженера, который будет дежурить в ночь релиза.
Момент, когда инфраструктура переехала в панель управления
Современный разработчик часто вообще не знает, где физически находится его Redis. Память, диск и сервер стали услугой, которую можно заказать, увеличить, перенести или удалить через панель управления.
Сначала эта история развивалась вокруг классического хостинга. Компании арендовали стойки, потом выделенные серверы у провайдера, а затем VDS. Потом хостинг начал взрослеть, и провайдеры стали продавать уже не просто «кусок сервера», а готовые инфраструктурные сценарии.
Бизнес начал приобретать виртуальные машины с быстрыми SSD, резервные копии, панели управления, балансировщики, объектные хранилища, управляемые базы данных, кластеры Kubernetes, Redis и другие сервисы, которые раньше требовали человека с доступом по SSH, привычкой читать логи ночью и не самым здоровым отношением к кофе. А облака уже довели эту логику до глобального масштаба.
И вот теперь вместо покупки физической памяти мы выбираем тариф, вместо замены диска руками включаем резервную копию, а вместо отдельного сервера под Redis берём виртуальную машинку, managed-сервис или контейнерный кластер. Но история вычислений циклична — сначала мы экономили каждый килобайт на собственном железе, потом немного расслабились на первых виртуалках, а сейчас снова вспомнили, что бесконечных ресурсов не бывает.
Вместе с хостингом и managed-сервисами индустрия снова начала учиться экономить память. Вернулись разговоры про TTL, политики вытеснения, разделение горячих и холодных данных, сжатие, HyperLogLog, Bloom-фильтры, многоуровневое хранение и осторожную работу с размером ключей.
Почему ИИ снова сделал память главным узким местом
Есть забавная закономерность — каждый раз, когда инженеры считают, что наконец разобрались с памятью, выясняется, что проблема была гораздо шире. Сначала нужно было просто хранить данные, потом быстро их читать, потом не терять при сбоях, потом синхронизировать между машинами, потом уменьшить задержку, а потом сделать так, чтобы пользователь вообще не заметил всей этой акробатики.
Сейчас память всё меньше похожа на пассивное хранилище и всё больше становится частью самих вычислений, особенно в ИИ. И неудивительно, что проблема с памятью опять шире — вычислять мы научились быстро, хранить веса моделей тоже, а вот постоянно гонять данные между памятью и вычислительными блоками становится всё труднее. Узким местом оказывается уже не только вычислительная мощность, но и пропускная способность памяти вместе с задержкой доступа.
Инженеры даже придумали для этого отдельный термин — memory wall, или «стена памяти». Процессоры научились считать быстрее, чем память успевает «подвозить» им данные.
В этом есть почти киберпанковская ирония. Мы строим модели с сотнями миллиардов параметров, а затем обнаруживаем, что значительная часть ресурсов уходит на то, чтобы нужные данные вовремя доехали до вычислителя. Именно из-за этого растёт интерес к HBM — памяти с высокой пропускной способностью. В отличие от обычной DRAM, она размещается ближе к вычислительным чипам, соединяется с ними широкими каналами передачи данных и становится частью общей вычислительной архитектуры.
Отсюда и интерес к новым связям между процессорами, ускорителями и памятью: CXL, распределённой памяти, вычислениям рядом с данными и архитектурам, где хранение уже не стоит отдельно от обработки. Индустрия снова пытается сделать то, что делала всегда, только на новом уровне сложности — сократить путь данных до вычислителя, потому что в современных системах дорого уже не только считать, но и постоянно «возить» информацию туда-сюда.
Эта же логика видна по стеку. Данные всё чаще разделяют по температуре: «горячие» размещают ближе к приложению, «тёплые» отправляют в более дешёвое хранилище, «холодные» убирают в архив. В свою очередь, для поиска строят индексы и векторные базы, например, Pinecone, Weaviate и Qdrant помогают не просто достать запись по точному ключу, а найти близкие по смыслу фрагменты данных, чтобы система меньше блуждала по хранилищу.
В итоге вся история работы с памятью и данными оказывается историей инженерных иллюзий, которые постепенно становятся нормой. Сначала мы учим компьютер делать вид, что памяти больше, чем есть физически, потом заставляем диски быть вместе надёжнее, чем они есть по отдельности, затем прячем задержки за кэшами, а железо — за панелью управления. И каждый раз эта иллюзия работает ровно до того момента, пока нагрузка не напоминает, что под всеми абстракциями всё ещё живёт физика…
А как вам кажется, куда дальше будут развиваться технологии работы с памятью и данными? Делитесь мыслями в комментариях.