Что такое прогрев кэша

Обновлено: 07.07.2024

Уменьшим временно размер буферного кэша, чтобы упростить наблюдение за ним.

Изменение требует перезапуска сервера.

Проверим размер кэша:

Содержимое буферного кэша можно посмотреть с помощью расширения:

Создадим для удобства представление:

Условие на базу данных необходимо, так как в буферном кэше содержатся данные всего кластера. Расшифровать мы можем только информацию из той БД, к которой подключены. Глобальные объекты считаются принадлежащими БД с нулевым OID.

Используя это расширение, можно наблюдать за состоянием кэша с разных сторон.

Кроме информации о том, как представлена в кэше та или иная страница, можно, например, посмотреть распределение буферов по их "популярности":

Можно посмотреть, какая доля каких таблиц закэширована (и насколько активно используются эти данные):

Подобные запросы могут подсказать, насколько активно используется буферный кэш и дать пищу для размышлений о том, стоит ли увеличивать или уменьшать его размер.

Надо учитывать, что такие запросы:

  • надо повторять несколько раз: цифры будут меняться в определенных пределах;
  • не надо выполнять постоянно (как часть мониторинга) из-за блокировок буферного кэша.

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

Посмотрим на расширение для прогрева кэша:

Например, сейчас в кэше нет таблицы test (мы перезагружали сервер):

В простейшем виде вызов функции считывает указанную таблицу в буферный кэш.

Изменим одну строку таблицы:

Как объяснить такой результат?

Изменились две табличные страницы (на одной версия строки удалена, в другую - добавлена), в кэш прочитана карта свободного пространства и карта видимости (которая, к тому же, изменилась).

Следует учитывать, что расширение pg_buffercache накладывает блокировки на время доступа к кэшу, поэтому не следует использовать его слишком часто на производственном сервере.

Расширение pg_prewarm может использоваться и для прогрева кэша операционной системы. А в версии PostgreSQL 11 оно получит возможность сохранять актуальное состояние кэша на диск и восстанавливать его же после перезагрузки сервера.

«Предел упругости» веб-сервиса

Знание «предела» оптимальной работы веб-сервиса важно при обеспечении его стабильности. Понятно, что в случае DDoS этот предел может быть превышен в десятки, сотни или тысячи раз, но в случае ежедневной посещаемости всплески (уже достаточно большой нагрузки) будут только трех-пятикратными: т.е. достаточно иметь 5-кратный запас «прочности» по посещаемости веб-сервиса, чтобы гарантировать стабильную его работу в 99,9% случаев. Здесь и далее речь идет про дневную посещаемость 100 тысяч посетителей и выше.

Даже если у вас нет пятикратного запаса по прочности, то понимание, где конкретно находится «предел» стабильности, и как после прохождения этого предела сервис будет себя вести, — полезно. Кто осведомлен, тот вооружен.

  1. Время ответа сервера после прохождения предела будет расти быстрее, чем до него («сломается» линейность роста времени ответа сервера).
  2. Появятся сетевые или серверные ошибки (сервер(ы) не будет успевать обрабатывать все запросы).

Практическое использование «предела упругости»

  1. Рассчитать нагрузку, при которой будет обеспечиваться KPI по времени ответа сервера (например, при 1000 запросов в секунду медианное время будет не больше 200 мс).
  2. Рассчитать увеличение серверных мощностей, которые будут гарантировать KPI по времени ответа (если сейчас он не достигается) или потребуются при росте нагрузки (например, с 1000 до 1500 запросов в секунду).
  3. Предупредить ситуации отказа веб-сервиса (если окажется, что ежедневные пики нагрузки уже превышают «предел упругости»): ведь при незначительном превышении нагрузки может произойти полный отказ в обслуживании.
  4. Получить расчетные значения нагрузки для ситуации «прогрев кэша» (обсудим чуть ниже).

Полезно также знать реальный «предел прочности» веб-сервиса, но по опыту он не превосходит +30% от «предела упругости» (серверы достаточно быстро отказывают из-за лавинообразного роста нагрузки, когда небольшие задержки приводят к увеличение очереди запросов и превышению времени ожидания ответа уже для большинства входящих запросов).

«Прогрев кэша»

Возможна редкая, но очень неприятная ситуация: когда в случае массового обновления записей (страниц) необходимо их все максимально оперативно заменить на новые. Это может быть новый вызов кода, удаление вирусных вставок или исправление технической ошибки. А кэширование сайта позволяет работать в «зоне упругости» и гарантировать линейный рост времени ответа при увеличении нагрузки.

Резкий сброс кэша («прогрев») сразу выводит сайт в зону нестабильной работы или даже за пределы «предела прочности», поэтому недопустим. Существуют два (принципиально схожие) подхода для решения этой задачи.

b_591aaacd7327d.jpg

Первый — это «прогрев» кэширующих серверов по очереди, предполагая, что «прогрев» каждого из них не выводит сайт из «зоны упругости». Характерный график такого «прогрева» показан ниже: число запросов резко возрастает, быстро возвращается к пониженному значению, потом ситуация повторяется до тех пор, пока все кэширующие серверы не будут более-менее «прогреты». Для описания этого процесса я использую термин «Каскадный сброс кэша».Возможна оптимизация описанного процесса, например, за счет синхронизации кэшей между серверами, в теории, можно добиться меньшего роста нагрузки при «прогреве» очередного сервера. Но на практике либо кэш серверов несколько различается (пересечение кэшей не более 20-30%), поэтому взаимное использование не дает кратковременного эффекта. Либо частота запросов к «прогретым» данным достаточно высока, и «прогрев» нового сервера происходит очень быстро (как на графике выше), поэтому синхронизация не требуется.

Нужен совет в решении такой проблемы:
Есть некое приложение , выполняющее запросы по такому принципу
app-->app_cache()--(if not found)-->database()
app_cache содержит некую часть БД, по расчётам самую востребованную.
Для запросов , выходящих за app_cache, используется БД.
Проблема в том, что
во-первых, усолвия такие, что возможны большие просмотры данных
во-вторых, БД находится в холодном состоянии, что влечет задержки
при выполнении первого запроса к БД.

Известны объекты, к которым возможны "тяжелые" запросы,
их суммарный объём чуть больше 10 гб.
Размер кэша - 40-50 Гб
На первый взгляд, проблему можно легко решить

Но как показали тесты, при размере кэша в 500мб
например, таблица размером в 50мб
читается в кэш в 2 захода, а не в 1, как хотелось бы.

Если я правильно помню, в нормальных условиях в
1 заход в кэш читается "short table"
а если я говорю таблице alter table tab1 cache, то она
должна вести себя как short (чего не наблюдается)
Возможно, я и ошибаюсь.
Поэтому очень нужен совет, как же мне правильно разогреть кэш.

можно подробнее, что именно не понятно?
Обращаю внимание, что данные в app_cache попадают не из БД.

хм, а Том говорит они практически не отличаются
devil in details?

хм, а Том говорит они практически не отличаются
devil in details?

можно подробнее, что именно не понятно?
Обращаю внимание, что данные в app_cache попадают не из БД.

можно подробнее, что именно не понятно?
Обращаю внимание, что данные в app_cache попадают не из БД.

Данные берутся из буфферного кэша, если они там есть
Если их там нет(первый запуск приложения) будут физические чтения
Собственно вопрос и стоит в том, как прогреть кэш и избежать физ чтений.

SQL*Plus
Oleg Afanasiev,
?

SQL*Plus
Oleg Afanasiev

Поскольку у вас Oracle Database 11g Enterprise Edition рекомендую попробовать для ваших запросов Result Cache.
Если запросы часто повторяются и в результате возвращают небольшой объем данных, то Result Cache - это самое то.
Тогда вам не придется "городить" какой-то самопальный кэш приложения.

result cache здесь не подойдёт к сожалению

Данные берутся из буфферного кэша, если они там есть
Если их там нет(первый запуск приложения) будут физические чтения
Собственно вопрос и стоит в том, как прогреть кэш и избежать физ чтений.

Кеширование — механизм, с помощью которого можно повысить скорость работы приложения за счёт переноса часто используемых данных в очень быстрое хранилище.


Кэширование очень активно используют во множестве систем. Например:

  • Внутренний кэш баз данных.
  • DNS кэш внутри нашего компьютера или браузера.
  • Кэш статического контента в браузере.
  • CDN также является своего рода кэшем.

В любом приложении есть операции, которые долго выполнялись, но результат которых можно сохранить на какое-то время. Это позволит меньше выполнять таких операций и отдавать заранее сохранённые данные.

Что можно кэшировать?

  • Запросы в базу данных.
  • Пользовательские сессии.
  • Медленные операции внутри приложения (расчеты, какие-то итоговые данные и т. д.)
  • Запросы к внешним системам.

Алгоритм работы

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

Стратегии кэширования

Cache Aside


Самый простой способ кэширования, зачастую множество фреймворков уже имеют встроенную реализацию.

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

  • Отлично подходит для тяжелых операций чтения.
  • Обычно система устойчива к отказу кэша. Если он упадет всегда можно пойти напрямую в базу данных.
  • Возможно использовать разные структуры данных для кэша и базы данных. Особенно полезно когда нам нужно закешировать результат какой-то сложной выборки
  • Из-за того что запись идет напрямую в базу данных, данные в кэше могут стать не консистентными. Для этого нужно использовать TTL (время жизни данных в кэше) или инвалидировать кэш, когда нужно гарантированно отдавать актуальные данные.

Read Through


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

  • Отлично работает с тяжелыми операциями чтения.
  • Данные всегда в консистентном виде.
  • Модель данных в кэше и в базе данных не могут отличатся.
  • Первый запрос в кэш всегда будет приводить к промаху и последующему запросу в БД. Эту проблему можно — решить с помощью “прогревания” кэша.

Write Through


Эта стратегия подразумевает приложение сначала запишет данные в кэш, после чего сохранит их в базу данных.

Лучше всего использовать эту стратегию вместе с read-through подходом. В таком случае мы получаем плюсы двух стратегий.

  • Гарантирует полною консистентность данных.
  • Отлично работает с тяжелыми операциями записи.
  • Добавляет дополнительную задержку для операций записи.


Самый сложный способ кэширования, в нем все операции записи происходят только в кэше, откуда они с некоторой задержкой попадают в основное хранилище.

  • Позволяет сильно оптимизировать сложные операции записи.
  • Данные всегда в консистентном виде.
  • Сложность реализации.
  • Есть шанс потерять данные если произойдет сбой кэша до того как данные запишутся в основное хранилище.

Алгоритмы вытеснения

Если в кэше нет свободного места для новых данных, то в работу вступают разнообразные механизмы вытеснения (очистки) кэша.

  • LRU (Least recently used) — алгоритм, который находит и вытесняет данные, которые не использовались дольше всех.
  • MRU (Most Recently Used) — вытесняются последние используемые данные.
  • LFU (Least Frequently Used) — вытесняются редко запрашиваемые данные.

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

Проблемы с кэшированием

В процессе создания и работы кэширующей системы может возникнуть набор разные проблем и вопросы, такие как:

  • Деление данных между кэширующими серверами.
  • Параллельные запросы на обновление данных.
  • “Холодный” старт приложения.

Деление данных между кэширующими серверами
Для повышения надежности и производительности системы кеширования приходится разделять ее на несколько серверов. Поэтому возникает вопрос как делить данные между серверами.

Вариант 1. Использовать хеширование ключей. В таком случае данные разделяются по серверам в зависимости от ключа кэширования. Для этого используется хеш функция, которая на вход принимает ключ и возвращает номер сервера.

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

Вариант 2. Логическое разделение данных на основе какого-то признака. Например мы можем разделять данные на основании пользователя. Так данные одного пользователя будут лежать рядом на одном сервере.
Примеры проблем и их решения отлично описаны в статье “Проблемы при работе с кэшем и способы их решения”

Параллельные запросы на обновление данных

Время от времени данные в кеше протухают и удаляются. В таком случае их необходимо обновить. Обычно это происходит, когда запрос обращается в кэш, видит, что данных нет, идет за ними в БД после чего обновляет кэш. Может возникнуть ситуация, когда таких запросов нескольколько, тогда все они пойдут в базу данных и нагрузят систему.

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

Решение 2. Фоновое обновление кэша. Приложение всегда читает данные из кеша и никогда не ходит в базу данных. Данные в кеше обновляет специальный скрипт или программа, которая работает в фоне. В таком случае никогда не наступит параллельного обновления кеша. Но возникает проблема с временем реакции на изменение данных в БД.

Решение 3. Вероятностное обновление данных. Обновляем не только данные, которых нет в кэше, но и с какой-то вероятностью те что уже есть. Это позволит обновить данные, до того как они протухнут и будут удалены.

Решение 4. Дублирование ключей. В системе есть два ключа, где второй имеет время жизни немного больше чем первый. В таком случае после того как исчезнет первый ключ мы обновляем его данные, но остальные запросы на чтение могут взять данные из второго ключа.

«Холодный» старт приложения
В момент запуска приложения данных в кэше может не быть. Как только пойдут запросы от пользователей все они пойдут массово в базу данных и начнуть одновременно обновлять кэш. Такая ситуация может привести к резкому падению производительности всей системы.

Решение. Можно прибегнуть к технике «прогревания» кеша. В таком случае при старте приложения мы также наполняем кэш данными, которые активно используются.

Итого

Кэширование это очень мощный и простой в использовании механизм, который позволяет значительно увеличить производительность системы. Если вы планируете использовать кэш, то стоит внимательно посмотреть на то какие данные вы хотите кэшировать и как они используются. От этого зависит эффективность решения и какую стратегию выбрать.

Читайте также: