Что такое page cache
Что такое кэширование сайта и почему это важно
Кэширование сайтов — это одна из наиболее полезных технологий. Ее применение делает сайты чрезвычайно быстрыми, что приводит к улучшению SEO и повышению удовлетворенности пользователей. Не говоря уже о более высокой конверсии, которую дает интернет кэш.
Что такое кэширование?
Сама идея реализации кеширования проста. Позвольте мне привести пример.
Если я спрошу вас, сколько будет 5 умножить 3, вы поймете, что правильный ответ 15. При этом не нужно его вычислять — вы просто помните результат, и не осуществляете никакой умственной обработки. Примерно так и работает кеширование.
Сайты тысячи, а иногда и миллионы раз в месяц. Каждый раз, когда браузер запрашивает веб-страницу, сервер должен выполнять кучу сложных вычислений. Он извлекает последние записи, генерирует шапку и подвал сайта, находит виджеты боковой панели и так далее. Но во многих случаях результат вычислений будет неизменным. Здорово, если бы мы могли заставить сервер запомнить окончательный результат, а не обрабатывать каждый запрос отдельно. Это именно то, что делает кеширование!
Как обслуживаются страницы с кэшем
Интернет кэш — что это такое? Сейчас поясню. Допустим, у вас есть блог с включенным кэшированием. Когда кто-то посещает главную страницу вашего блога в первый раз, он получает ее обычным способом: запрос обрабатывается на сервере, и полученная веб-страница, которая должна быть отображена, преобразуется в HTML-файл и отправляется в браузер посетителя.
Но что, если мой контент изменяется?
Это звучит здорово, но что, если вы включили кэширование, а затем опубликуете новую запись? Не будет ли она находиться вне кэша и не окажется ли невидимой для посетителей? Правильно настроенные системы кэширования прекрасно справляются с такими сценариями.
Система кэширования состоит не только из механизма хранения подготовленных HTML-файлов, но и механизма очистки кэша, когда выполняются определенные условия. Например, происходит публикация нового контента.
Является ли кэширование эффективным?
Сайт, разработанный и реализованный надлежащим образом, может загружаться всего за две секунды. Разве это недостаточно быстро? Необходимо ли использовать кэширование? Ответ — однозначно, да.
Используя кэширование в браузере и на сервере, вы все равно сможете сократить время загрузки. А когда речь идет о скорости загрузки, всегда стоит сделать так много, как только возможно!
Типы кэширования
Существует два типа кэширования — серверный и браузерный. Давайте рассмотрим различия между ними.
Кэширование в браузере
Перед тем, как почистить кэш в интернет эксплорер, нужно понимать, что кэширование позволяет браузеру хранить эти файлы какое-то время, поэтому не нужно извлекать их каждый раз, когда вы посещаете сайт. Например, при первом посещении сайта вы получите кучу ресурсов, которые браузер будет кэшировать. Это займет несколько секунд, но в следующий раз, когда зайдете на сайт, вы заметите значительное снижение времени загрузки.
Кэширование на сервере
Вместо обработки каждого запроса сервер принимает результаты этих запросов и сохраняет их. Затем он обслуживает сохраненные результаты, делая все намного быстрее.
Возможно, вы столкнетесь с терминами « кэш объектов » и « полный кэш страниц ». Оба обозначают методы кэширования на сервере. Кэш полной страницы — это то, о чем мы говорили до сих пор.
Кэш объектов хранит только фрагменты данных, а не полную страницу. Это может быть полезно при сохранении результата сложных операций, таких как создание меню навигации.
Кэширование в WordPress
Есть три вещи, которые нужно знать о кешировании в WordPress: написание эффективного кода, использование плагинов кэширования и использование встроенного кэша хостинга.
Использование плагинов кэширования WordPress
Самое важное правило – никогда не используйте одновременно больше одного плагина кэша страниц интернета. Это не сделает ваш сайт быстрее, а намного медленнее и в результате просто сломает.
Использование кэширования, осуществляемого хостингом
Написание эффективного кода
Например, если вы получаете метаданные для записи, и вызываете get_post_meta($post_id, ‘co-author’, true );,WordPress извлекает все метаданные для этого поста. Поэтому наличие 50 отдельных запросов get_post_meta() для извлечения одной записи не является расточительством.
Заключение
Кэш сайтов в интернете — это технология, которая увеличивает скорость работы сайта, не жертвуя при этом чем-либо значительно. При правильном использовании она не только приведет к значительному ускорению процесса загрузки страниц, но и уменьшит нагрузку на сервер.
Если вы еще не кэшируете свой сайт, сделайте это! Чтобы начать работу с кэшированием, ознакомьтесь с упомянутыми выше плагинами.
Пожалуйста, опубликуйте ваши мнения по текущей теме материала. За комментарии, отклики, подписки, дизлайки, лайки низкий вам поклон!
Дайте знать, что вы думаете по данной теме материала в комментариях. За комментарии, подписки, лайки, дизлайки, отклики огромное вам спасибо!
Обзор кэширования
Кэширование помогает значительно повысить производительность приложений и снизить затраты, независимо от масштаба
Что такое кэширование?
В сфере вычислительной обработки данных кэш – это высокоскоростной уровень хранения, на котором требуемый набор данных, как правило, временного характера. Доступ к данным на этом уровне осуществляется значительно быстрее, чем к основному месту их хранения. С помощью кэширования становится возможным эффективное повторное использование ранее полученных или вычисленных данных.
Как работает кэширование?
Данные в кэше обычно хранятся на устройстве с быстрым доступом, таком как ОЗУ (оперативное запоминающее устройство), и могут использоваться совместно с программными компонентами. Основная функция кэша – ускорение процесса извлечения данных. Он избавляет от необходимости обращаться к менее скоростному базовому уровню хранения.
Небольшой объем памяти кэша компенсируется высокой скоростью доступа. В кэше обычно хранится только требуемый набор данных, причем временно, в отличие от баз данных, где данные обычно хранятся полностью и постоянно.
Обзор кэширования
ОЗУ и работающие в памяти сервисы. Поскольку ОЗУ и работающие в памяти сервисы обеспечивают высокие показатели скорости обработки запросов, или IOPS (количество операций ввода-вывода в секунду), кэширование повышает скорость извлечения данных и сокращает расходы при работе в больших масштабах. Чтобы обеспечить аналогичный масштаб работы с помощью традиционных баз данных и оборудования на базе жестких дисков, требуются дополнительные ресурсы. Использование этих ресурсов приводит к повышению расходов, но все равно не позволяет достигнуть такой низкой задержки, какую обеспечивает кэш в памяти.
Области применения. Кэш используется на разных технологических уровнях, включая операционные системы, сетевые уровни, в том числе сети доставки контента (CDN) и DNS, интернет-приложения и базы данных. С помощью кэширования можно значительно сократить задержки и повысить производительность операций ввода-вывода в секунду для многих рабочих нагрузок приложений с большой нагрузкой на чтение, например порталов для вопросов и ответов, игровых ресурсов, порталов для распространения мультимедиа и социальных сетей. Кэшировать можно результаты запросов к базам данных, вычислений, которые требовательны к ресурсам, запросы к API и ответы на них, а также веб-артефакты, например файлы HTML, JavaScript и изображений. Рабочие нагрузки, требующие больших вычислительных мощностей для обработки наборов данных, например сервисы рекомендаций и высокопроизводительное вычислительное моделирование, тоже могут эффективно использовать уровень данных в памяти в качестве кэша. В этих приложениях можно обращаться к очень большим наборам данных в режиме реального времени через кластеры машин, которые охватывают сотни узлов. Управление этими данными в дисковом хранилище является узким местом таких приложений из-за низкой скорости работы базового оборудования.
Шаблоны проектирования. В среде распределенных вычислений выделенный уровень кэширования позволяет системам и приложениям работать независимо от кэша. При этом их жизненные циклы не влияют на кэш. Кэш служит центральным уровнем, к которому могут обращаться различные несвязанные между собой системы. Он имеет собственный жизненный цикл и архитектурную топологию. Это особенно важно для систем, в которых узлы приложений можно динамически масштабировать в обе стороны. Если кэш находится на том же узле, что и приложение или системы, которые им пользуются, масштабирование может разрушить целостность кэша. Кроме того, если используются локальные кэши, это дает преимущества только локальным приложениям, которые пользуются данными. В распределенной среде кэша данные могут охватывать множество серверов кэширования и находиться в центральном расположении, удобном для всех потребителей данных.
Рекомендации по кэшированию. При реализации уровня кэша необходимо принимать во внимание достоверность кэшируемых данных. Эффективный кэш обеспечивает высокую частоту попаданий, то есть наличия в кэше запрашиваемых данных. Промах кэша происходит, когда запрашиваемых данных в кэше нет. Для удаления из кэша неактуальных данных применяются такие механизмы, как TTL (время жизни). Следует также понимать, требуется ли для среды кэширования высокая доступность. Если она необходима, можно использовать сервисы в памяти, такие как Redis. В ряде случаев уровень в памяти можно использовать как отдельный уровень хранения данных, в отличие от кэширования из основного хранилища. Чтобы решить, подходит ли такой вариант, необходимо определить для данных в сервисе в памяти соответствующие значения RTO (требуемое время восстановления, то есть сколько времени требуется системе на восстановление после сбоя) и RPO (требуемая точка восстановления, то есть последняя восстанавливаемая точка или транзакция). Для соответствия большинству требований RTO и RPO можно применять характеристики и проектные стратегии разных сервисов в памяти.
Уровень | Клиентские | DNS | Интернет | Приложение | База данных |
Пример использования | Определение IP-адреса для домена | Ускорение получения веб-контента от серверов веб-приложений Управление веб-сеансами (на стороне сервера) | Повышение производительности приложений и ускорение доступа к данным | Сокращение задержек, связанных с запросами к базе данных | |
Технологии | Управление кэшированием с помощью HTTP-заголовков (браузеры) | Серверы DNS | Управление кэшированием с помощью HTTP-заголовков, CDN, обратные прокси-серверы, веб-ускорители, хранилища пар «ключ – значение» | Хранилища пар «ключ – значение», локальные кэши | Буферы баз данных, хранилища пар «ключ – значение» |
Решения | Для браузеров | Amazon Route 53 | Amazon CloudFront, ElastiCache для Redis, ElastiCache для Memcached, решения партнеров | Инфраструктуры приложений, ElastiCache для Redis, ElastiCache для Memcached, решения партнеров | ElastiCache для Redis, ElastiCache для Memcached |
Кэширование с помощью Amazon ElastiCache
Веб-сервис Amazon ElastiCache упрощает развертывание, эксплуатацию и масштабирование в облаке хранилища или кэша в памяти. Сервис повышает производительность интернет-приложений, позволяя получать информацию из быстрых управляемых хранилищ данных, размещенных в памяти, а не только из баз данных, размещенных на дисках и работающих не так быстро. Информацию о том, как реализовать эффективную стратегию кэширования, см. в этом техническом описании по кэшированию в памяти.
Преимущества кэширования
Повышение производительности приложений
Поскольку память работает в разы быстрее диска (магнитного или SSD), чтение данных из кэша в памяти производится крайне быстро (за доли миллисекунды). Это значительно ускоряет доступ к данным и повышает общую производительность приложения.
Сокращение затрат на базы данных
Один инстанс кэша может обрабатывать тысячи операций ввода-вывода в секунду, потенциально заменяя несколько инстансов базы данных, что в результате дает снижение общих затрат. Это особенно важно, если плата взимается за пропускную способность базы данных. В таких случаях можно снизить затраты на десятки процентов.
Снижение нагрузки на серверную часть
Благодаря освобождению серверной базы данных от значительной части нагрузки на чтение, которая направляется на уровень памяти, кэширование может сократить нагрузку на базу данных и защитить ее от снижения производительности под нагрузкой и даже от сбоев при пиковых нагрузках.
Прогнозируемая производительность
Общей проблемой современных приложений является обработка пиков в использовании приложений. Примерами могут служить социальные сети во время Суперкубка или в день выборов, веб-сайты электронной коммерции в Черную пятницу и т. д. Повышенная нагрузка на базу данных приводит к повышению задержек при получении данных, и общая производительность приложения становится непредсказуемой. Эту проблему можно решить благодаря использованию кэша в памяти с высокой пропускной способностью.
Устранение проблемных мест в базах данных
Во многих приложениях небольшое подмножество данных, например профиль знаменитости или популярный продукт, может оказаться намного более востребованным, чем остальные данные. Это приводит к появлению проблемных мест в базе данных и требует избыточного выделения ее ресурсов, чтобы удовлетворить спрос на пропускную способность, которой достаточно для получения наиболее часто используемых данных. За счет хранения общих ключей в кэше в памяти можно избавиться от необходимости избыточного выделения ресурсов и обеспечить быструю и предсказуемую работу системы при обращении к самым востребованным данным.
Повышение пропускной способности операций чтения (количество операций ввода-вывода в секунду)
Помимо сокращения задержек, системы в памяти обеспечивают намного более высокую скорость выполнения запросов (количество операций ввода-вывода в секунду) по сравнению с базами данных на диске. Один инстанс, который используется как распределенный дополнительный кэш, может обслуживать сотни тысяч запросов в секунду.
Magento Enterprise: Что такое Full Page Cache и почему он нужен
Magento Enterprise: Что такое Full Page Cache и почему он нужен.
Для тех, кто знаком с Magento, не секрет, что этот e-commerce движок довольно требователен к железу. Но разработчики этого интернет-магазина попытались решить эту проблему и придумали много различного рода «ускорялок», без которых, пожалуй, запускать магазин на движке Magento в продакшн не стоит. Слишком долго Magento будет отдавать конечному пользователю страницу. Среди таких «ускорялок» кеши, индексы, компиляция, объединение JS/CSS в один сжатый файл и др.
Одной из основных «фишек» Magento Enterprise является Full Page Cache (далее FPC). Эту «фишку» реализует модуль Enterprise_PageCache, входящий в состав пакета Magento Enterprise.
В статье рассматривается самая свежая на момент написания статьи версия Magento Enterprise: 1.13.1.
FPC позволяет отдавать серверу страницу за считанные миллисекунды, практически не нагружая сервер. Я провел замеры времени отдачи страницы продукта сервером (в одном из проектов, над которым работал), вот результаты:
Что и когда кеширует FPC
Как следует из названия, Full Page Cache кеширует полностью всю страницу. Но кеширует не все страницы. Как минимум потому, что для этого нет смысла. По умолчанию кешируются только страницы продукта, страницы категории, CMS-страницы и страница с 404 ошибкой (страница не найдена). В этом можно убедиться, посмотрев конфигурацию модуля (config.xml):
В секции frontend/cache/requests здесь указывается frontName контроллера модуля (его значение хранится в конфиге модуля по пути: frontend/routers/route_name/args/frontName), затем контроллер и экшен (контроллер и экшен — необязательные параметры). А передаваемое значение — процессор реквеста (запроса).
Вы можете точно так же заставить кешировать контроллеры/контроллер/экшен вашего модуля, достаточно добавить в нужную секцию данные аналогично тому, как это делает модуль Enterprise_PageCache. Пример:
При этом есть ряд условий, при которых FPC не кеширует страницы. Не кешируются, к примеру, HTTPS страницы, страницы с GET-параметром no_cache. Методы canProcessRequest и isAllowed класса Enterprise_PageCache_Model_Processor:
Как работает FPC
Если страница кешируется FPC-кешем, то FPC отключает стандартный кеш блоков. См. метод processPreDispatch класса Enterprise_PageCache_Model_Observer, который срабатывает, когда возникает событие (event) controller_action_predispatch:
FPC генерирует для каждого HTTP-запроса свой идентификатор кеша, который будет использован для сохранении страницы в кеш. Идентификатор кеша зависит от нескольких параметров: авторизован кастомер или нет, к каким сегментам он относится, к какой группе пользователей относится и пр. Посмотреть, как генерируется этот идентификатор, можно в методе _createRequestIds класса Enterprise_PageCache_Model_Processor:
FPC использует плейсхолдеры. Они в Magento добавляются с помощью файла конфигурации cache.xml в папке etc модуля. А плейсхолдер обрабатывается контейнером плейсхолдера. Контейнер — это класс, который будет обрабатывать плейсхолдер во время рендеринга FPC (процесс рендеринга блока FPC-кешем отличается от обычного рендеринга блока). Пример файла cache.xml:
Кратко о конфигурации плейсхолдера:
Конструктор класса Enterprise_PageCache_Model_Container_Placeholder:
В будущем в классе контейнера можно будет получить атрибуты блока методом getAttribute:
Методы для обёртки плейсхолдером контента блока:
Пример обёртки плейсхолдером контента блока:
Перед тем, как производится отправка ответа на запрос, срабатывавает событие controller_front_send_response_before и выполняется метод cacheResponse класса Enterprise_PageCache_Model_Observer, который сохраняет страницу в кеш, если это необходимо. Код метода cacheResponse:
Здесь метод processRequestResponse сохраняет всю страницу и нужные данные в кеш, если это нужно:
В итоге в кеше страницы будет содержаться информация о блоке вместо содержимого блока. Эта информация поможет отрендерить блок в будущем. Вот пример такой информации, которую FPC будет заменять на содержимое блока во время своего рендеринга:
При следующей загрузке этой страницы Magento загрузит эту страницу из кеша (см. метод extractContent класса Enterprise_PageCache_Model_Processor). Если в кеше пусто — обычный рендеринг с инициализацией Magento (как будто FPC и не было) с последующим сохранением в кеш страницы. Если же страница есть в кеше, то FPC будет обрабатывать контент из этого кеша.
Методы _processContent и _processContainers класса Enterprise_PageCache_Model_Processor:
Как видно из кода этих методов, обрабатываются только блоки, у которых есть плейсхолдеры. Если для вашего блока нет плейсхолдера, его содержимое не будет изменяться. Поэтому, если вы хотите выводить динамически изменяющиеся блоки, то для них необходимо создавать плейсхолдеры.
Контейнеры плейсхолдеров сначала обрабатываются методом applyWithoutApp. Этот метод пытается заменить содержимое блока в закешированной странице на нужное нам содержимое. Пример метода applyWithoutApp, абстрактного для всех контейнеров класса Enterprise_PageCache_Model_Container_Abstract:
Из кода понятно, что в случае, если вы хотите изменять блок динамически, вам необходимо определить метод _getCacheId контейнера исходя из логики вашего блока. Если хотя бы один контейнер не был обработан (applyWithoutApp вернул false), то его нужно рендерить (см. метод _processContent класса Enterprise_PageCache_Model_Processor), а при этом произойдёт инициализация Magento (выполнится Mage::app()). При этом запрос обрабатывается контроллером Enterprise_PageCache_RequestController экшеном process. Код экшена process:
Для каждого не обработанного контейнера запускается метод applyInApp, который должен отрендерить блок и заменить содержимое плейсхолдера в контенте. Код метода applyInApp, абстрактного для контейнеров класса Enterprise_PageCache_Model_Container_Abstract:
Здесь, как мы видим, содержимое получается методом _renderBlock класса контейнера. Этот метод, как правило, уникален для каждого контейнера и содержит какую-то особую логику. В абстрактном классе Enterprise_PageCache_Model_Container_Abstract для контейнеров этот метод возвращает false. Именно он должен возвращать HTML-содержимое блока.
Но, как мы помним, FPC сохраняет всю информацию, необходимую для рендеринга. Поэтому, если вы передали информацию в методе getCacheKeyInfo вашего блока для сохранения, вы сможете её задать во время FPC-рендеринга. Делать это нужно в методе _renderBlock контейнера. Получить в нём экземпляр блока можно методом _getPlaceHolderBlock:
Как видно, мы получаем экземпляр класса блока с установленным шаблоном. Пример метода _renderBlock:
Здесь, как видно из кода, мы передали блоку параметры handles и popup_ids. В самом же блоке их необходимо получать вот так:
Я надеюсь, данная статья приоткрыла завесу тайны над функционалом FPC, и вы узнали, как работает механизм FPC изнутри.
Кеш действительно эффективен и прекрасно работает, снижая нагрузку на сервер и обеспечивая быструю работу электронного магазина с высокой посещаемостью.
В моей следующей статье по FPC я опишу, как задавать свои собственные динамические блоки в Magento Enterprise для корректной работы дополнительного динамического функционала с включенным FPC.
Linux Page Cache для SRE: основные файловые операции и syscall’ы (часть 1)
В этой серии постов я хотел бы поговорить о Linux Page Cache. Я считаю, что данные знания теории и инструментов жизненно необходимы и важны для каждого SRE. Общее понимание как работает Page Cache помогает и в рутинных повседневных задачах, и в экстренной отладке на продакшене. При этом Page Cache часто оставляют без внимания, а ведь его лучшее понимание. как правило, приводит к:
более точному планированию емкости системы и лимитов сервисов и контейнеров;
улучшенным навыкам отладки приложений, интенсивно использующих память и диски (СУБД и хранилища данных);
созданию безопасных и предсказуемых сред выполнения специальных задач, связанных с памятью и/или вводом-выводом (например: сценарии резервного копирования и восстановления, rsync однострочники и т.д.).
Я покажу, какие утилиты вы можете использовать, когда имеете дело с задачами и проблемами, связанными с Page Cache, как правильно к ним подходить, и как понять реальное использование памяти.
Подготовка окружения
Начнём с подготовки окружения. Нам понадобиться файл для тестов:
И сбрасываем все кеши, чтобы получить чистую систему:
Теперь пришло время засучить рукава и приступить к практическим примерам.
Чтение файлов и Page Cache
Чтение файлов используя read() syscall
Результат должен выглядеть как-то так:
Из вывода видно, что системный вызов read() возвращает 4096 байт (одна страница) не смотря на то, что наш скрипт запрашивал только 2 байта. Это пример того, как python оптимизирует работу буферизованного ввода-вывода. Хотя это и выходит за рамки данного поста, но в некоторых случаях важно иметь это в виду.
Теперь давайте проверим, сколько данных закэшировало ядро. Для получения этой информации мы используем vmtouch :
Из вывода мы видим, что вместо 2B данных, которые запрашивал python, ядро закэшировало 80 КБ или 20 страниц.
Ядро линукс в принципе не может загружать в Page Cache ничего меньше 4 КБ или одной страницы. Но почему их там оказалось на 19 страниц больше? Это отличный пример того, как ядро использует опережающее чтение (readahead) и предпочитает выполнять последовательные операции ввода-вывода, а не случайные. Основная идея состоит в том, чтобы предсказать последующие чтения и свести к минимуму количество запросов к диску. Этим поведением можно управлять с помощью системных вызовов:
posix_fadvise() ( man 2 posix_fadvise ) и
readahead() ( man 2 readahead ).
Обычно, в продакшене для систем управления базами данных и дисковых хранилищ, не имеет большого смысла в настройках параметров опережающего чтения. Если СУБД не нужны данные, которые были кэшированы при опережающем чтении, политика восстановления памяти ядра (memory reclaim) должна в конечном итоге удалить эти страницы из Page Cache. Так же, как правило, последовательный ввод-вывод не является дорогостоящим для ядра и аппаратного обеспечения. В свою очередь отключение опережающего чтения вообще – может даже навредить и привести к некоторому снижению производительности из-за увеличения числа операций ввода-вывода в дисковых очередях ядра, бÓльшего количества переключений контекста (context switches) и бÓльшего времени для подсистемы управления памятью ядра для распознавания рабочего набора данных (working set). Мы поговорим о политике восстановления памяти (memory reclaim), нагрузке на память (memory pressure) и обратной записи в кэш (writeback) позже в этой серии постов.
Теперь давайте посмотрим как использование posix_fadvise() может уведомить ядро о том, что мы читаем файл случайным образом, и поэтому не хотим иметь никакого опережающего чтения (readahead):
Перед запуском скрипта нам нужно сбросить все кэши:
Теперь, если вы проверите выдачу vmtouch – вы можете увидеть, что, как и ожидалось, там находится лишь одна страница:
Чтение файлов с помощью системного вызова mmap()
Также в целях тестирования нам необходимо очистить кэш перед выполнением скрипта:
Теперь давайте посмотрим на содержимое Page Cache:
и содержимое Page Cache :
Как вы можете видеть с MADV_RANDOM нам удалось загрузить ровно одну страницу в Page Cache.
Запись в файл и Page Cache
Теперь давайте поэкспериментируем с записью.
Запись в файлы с помощью системного вызова write()
Давайте продолжим работу с нашим экспериментальным файлом и попробуем записать первые 2 байта:
Удалите все из Page Cache и запустите приведенный выше скрипт:
Теперь давайте проверим содержимое Page Cache.
Как вы можете видеть, в Page Cache находится 1 страница данных. Это достаточно важное наблюдение, так как, если происходят записи размером меньше размера страницы, то им будут предшествовать 4 Кб чтения, для того, чтобы загрузить данные в Page Cache.
Также мы можем проверить состояние грязных (dirty) страниц, заглянув в файл статистики памяти cgroup.
Получаем текущую cgroup:
Запись в файл с помощью mmap() syscall
Давайте теперь повторим наш опыт с записью но будем использовать в этот раз mmap() :
Грязные страницы кеша (dirty pages)
Как мы видели ранее, процесс генерирует грязные страницы путем записи в файлы через кэш.
Linux предоставляет несколько вариантов получения количества грязных (dirty) страниц. Первый и самый старый из них – это прочитать системный файл /proc/memstat :
Часто такую системную информацию трудно интерпретировать и использовать, поскольку мы не можем точно определить, какой процесс их сгенерировал и к какому файлу они относятся.
Поэтому, как было показано выше, лучшим вариантом для получения данной информации лучше всего использовать cgroup:
Private_Dirty – объем грязных данных, сгенерированных этим процессом;
Shared_Dirty – грязные страницы других процессов. Эта метрика будет отображать данные только для страниц, на которые есть ссылки (referenced memory). Это означает, что процесс должен был обратиться к этим страницам раньше и сохранить их в своей таблице страниц (page table) (подробнее позже).
Синхронизация данных файла: fsync(), fdatasync() и msync()
Мы уже использовали команду для синхронизации ( man 1 sync ) всех грязных страниц системы на диски перед каждым тестом, для того чтобы получить свежий Page Cache. Но что делать, если мы хотим написать систему управления базами данных, и нам нужно быть уверенными, что все записи попадут на диски до того, как произойдет отключение питания или другие аппаратные ошибки. Для таких случаев linux предоставляет несколько способов заставить ядро совершить сброс грязных страницы для конкретного файла из Page Cache на диски:
fsync() – блокируется до тех пор, пока не будут синхронизированы все грязные страницы конкретного файла и его метаданные;
fdatasync() – то же самое, но без метаданных;
флагами открытия файла: O_SYNC или O_DSYNC сделают все записи в файл синхронными по умолчанию.
Вам все еще нужно заботиться о барьерах записи (write barriers) и понимать, как работает ваша файловая система. Обычно операции добавления в конец файла безопасны и не могут повредить данные которые были записаны до этого Другие же типы операций записи могут повредить ваши файлы (например, даже с настройками журнала по умолчанию в ext4). Поэтому все системы управления базами данных, такие как MongoDB, PostgreSQL, Etcd, Dgraph и т. д., используют журналы предварительной записи (WAL). Если вам интересно узнать более подробнее об этой теме, – можно пожалуй начать с поста в блоге Dgraph.
А вот и пример синхронизации файлов:
Проверяем наличие данных файла в Page Cache с помощью mincore()
Настало время выяснить, каким же таким способом vmtouch удается показать нам, сколько страниц того или иного файла содержит Page Cache.
Секрет заключается в системном вызове mincore() ( man 2 mincore ). mincore() буквально означает “память в ядре” (memory in core). Его параметрами являются начальный адрес виртуальной памяти, длина адресного пространства и результирующий вектор. mincore() работает с памятью (а не с файлами), поэтому его можно использовать и для проверки, была ли вытеснена анонимная память в своп (swap).
mincore() returns a vector that indicates whether pages of the calling process’s virtual memory are resident in core (RAM), and so will not cause a disk access (pagefault) if referenced. The kernel returns residency information about the pages starting at the address addr, and continuing for length bytes.
Поэтому для повторения фичи vmtouch нам нужно сначала отобразить файл в виртуальную память процесса, даже если мы не собираемся выполнять ни чтение, ни запись.
И сверяем вывод с vmtouch :
Вывод
Как видно из статьи ядро Linux предоставляет широкий набор возможностей для взаимодействия и управления Page Cache, которые на мой взгляд должен знать каждый SRE.