Pull to refresh

Теория кэша

Website development *

Введение


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

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

Основные проблемы кэширования



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

Второй проблемой кэширования является проблема быстродействия. А не выполняются ли наш алгоритм без кэширования быстрее, чем с кэшированием? Несмотря на абсурдность с первого взгляда, она более чем имеет место. Дело в том, что алгоритмы кэширования тоже потребляют ресурсы, и запросто может случиться так, что количество потребляемых кэшем ресурсов превышает количество ресурсов для вычисления самих данных. Это часто случается в 2-х случаях. Первый случай — это когда сайт из 10-ти страниц сажают на мощный фреймворк. Тут все просто – исходных данных настолько мало, что скорость вычисления очень высока, а кэширование только тормозит работу. Второй случай обратный — когда сайт настолько большой, что размер кэша вырастает до объемов приводящих к существенному замедлению их поиска в кэше.

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

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

А вот что касается проблемы актуальности, тут все намного сложнее…

Теория кэша


Автор различает 4 основных типа кэширования информации:

1. Независимый или статичный – имеет место, когда не требуется проверка изменился ли объект. Алгоритм прост – если есть данные в кеше, то отдать данные, иначе их вычислить. Эффективно в рамках работы одного процесса, когда требуется частое использование результатов сложных промежуточных вычислений. После завершения процесса статичный кэш умирает и для повторного процесса все данные вычисляются вновь. Вобщем-то в любом языке программирования все временные переменные – ни что иное, как статичный кеш. Если же требуется кэширование результатов функции, то можно использовать такой алгоритм с использованием static-переменных на примере PHP:

function getData($id)
{
static $data = array();

if (isset($data[$id])) return $data[$id];

// вычисление данных
$data[$id] = $newData;

return $data[$id];
}


2. Явно-зависимый – имеет место, когда решение об обновлении кэша принимается по некоторому легко вычисляемому признаку. Сюда относится прежде всего кэширование данных взятых из определенного файла, а так же кэширование по времени. В этих случаях легко определить изменился ли файл или не истекло ли время существования кэша (и кэш явно зависит от этих факторов). Алгоритмы здесь тоже достаточно простые – сводятся к проверкам условий, но в отличие от статического кэша он может независимо использоваться разными процессами.

3. Неявно-зависимый – имеет место, когда изменение объекта кэширования зависит от множества факторов. Например, в состав объекта входит множество других объектов, которые тоже могут изменяться. То есть объект неявно (не на прямую) зависит от других, которые тоже могут зависеть от других и т.д. Совокупность этих факторов является неявными зависимостями объекта, и что бы принять решение о том, изменился ли объект нужно «опросить» их все, что не всегда возможно или целесообразно. Например, функция, которая показывает информацию, взятую из базы данных. Мы можем закешировать результат функции, но мы должны знать, когда данные изменятся, что бы их обновить. А это эквивалентно обращению к таблице, что по ресурсоемкости равносильно выполнению функции. А если таблиц много? Смысл кэша теряется.

Это раскрывается через так называемую «таблицу зависимостей». В этой таблице присутствует 2 столбца: объекты и время их изменения. При изменении объектов необходимо обновлять их времена в таблице. Скорость доступа к самой таблице очень высока, (как правило, она находится в статичном или явно-зависимом кеше), и получить времена изменения всех необходимых нам объектов можно очень быстро. И если хоть одно время изменения нужных объектов превышает время кэширования, то кэш необходимо сбросить. Таким образом, неявные зависимости превращаются в явные – объект зависит от некоторого набора времен в таблице зависимостей.

Приведу пример. Есть некий модуль CMS, который занимается отображением комментариев. У нас есть 2 таблицы в БД – пользователей и комментариев, которые связаны соотношением один-ко-многим. При изменении данных некоторого пользователя, мы устанавливаем текущее время в строке «users» в таблице зависимостей. Если изменились комментарии, мы аналогично поступаем со строкой «comments». Модуль знает, что он зависит от «users» и «comments» и если время хотя бы одного из них превышает время изменения кэша, то кэш сбрасывается, иначе — используется. Обращу внимание на то, что «users» и «comments» — это не обязательно время изменения таблицы, это скорее времена изменения некоторой сущности, которая может состоять из множества таблиц и других параметров.

4. Условно-зависимый – имеет место, когда неявно-зависимый кэш может быть приведен к явно-зависимому или статичному при выполнении некоторого условия. Например, можно утверждать, что время последнего изменения таблицы зависимостей – это время последнего изменения данных на сайте. Если для пользователя на странице нет уникальных данных (читай – он не залогинен), то вся страница будет зависеть только от таблицы зависимостей. А значит, всю страницу целиком можно положить в кэш, на данном условии. Сюда же относится кэш, который в нужный момент просто физически удаляется.

Заключение


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

Описанное мной – лишь основа. Тут можно много чего добавить, просто не хочется статью делать излишне большой. Если статья покажется интересной, я попробую написать продолжение.
Tags:
Hubs:
Total votes 130: ↑111.5 and ↓18.5 +93
Views 10K
Comments Comments 65