Что такое кеширование? - PullRequest
       43

Что такое кеширование?

65 голосов
/ 14 февраля 2009

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

Или как x, y, z в коде ваших программ могут повредить вашей способности кеширования.

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

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

Что такое кэширование и что это за типы?

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

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

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

Когда кто-то говорит, что нашел кусок кода, который повредил бы кеширование и после того, как они исправили это, он улучшился скорость их приложения, что они о чем?

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

Кроме того, что это действительно означает, когда кто-то говорит о базе данных кэширование? Это просто особенность они включаются в их базе данных? Делать Вы должны явно кэшировать значения или база данных выбирает, какие из них кеш для тебя?

Как самостоятельно начать кэширование элементов для повышения производительности?

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

Как насчет кэширования базы данных, как мне начать это? Я слышал о таких вещах, как memcache. Требуется ли утилита такого типа для кэширования в базах данных?

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

Ответы [ 9 ]

51 голосов
/ 14 февраля 2009

Кэширование - это просто практика хранения данных и извлечения данных из высокопроизводительного хранилища (обычно памяти) в явном или неявном виде.

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

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

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

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

  • Запустите запрос как отдельный процесс и поместите результат в кеш. Все страницы просто получают доступ к кешу. Вы можете обновлять кэшированную версию так часто, как это необходимо (один раз в день, один раз в неделю, один раз в 5 секунд, что угодно);
  • Кэширование прозрачно через вашего поставщика сохраняемости, ORM или что-то еще. Конечно, это зависит от того, какую технологию вы используете. Hibernate и Ibatis, например, поддерживают кэширование результатов запроса;
  • Попросите ваши страницы выполнить запрос, если результат не находится в кеше (или он «устаревший», то есть рассчитывается дольше, чем заданный «возраст»), и поместить его в кеш. Это приводит к проблемам параллелизма, если два (или более) отдельных процесса решат, что им нужно обновить результат, чтобы вы в итоге выполняли один и тот же (дорогой) запрос восемь раз за раз. Вы можете справиться с блокировкой кеша, но это создает еще одну проблему с производительностью. Вы также можете прибегнуть к методам параллелизма на вашем языке (например, API параллелизма Java 5).

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

  • Обновите кеш, а затем поставьте в очередь запрос на обновление соответствующего хранилища;
  • Запись через кеширование: поставщик кеша может предоставить механизм для сохранения обновления и блокировки вызывающей стороны до тех пор, пока это изменение не будет сделано; и
  • Кэширование с обратной записью: то же самое, что и кэширование с обратной записью, но оно не блокирует вызывающего. Обновление происходит асинхронно и отдельно; и
  • Модели персистентности как сервиса: это предполагает, что ваш механизм кэширования поддерживает некоторую наблюдаемость (то есть слушатели событий кэширования). По сути, совершенно отдельный процесс, неизвестный вызывающей стороне, прослушивает обновления кэша и сохраняет их при необходимости.

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

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

14 голосов
/ 14 февраля 2009

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

Обратите внимание на следующее:

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

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

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

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

Resultset Cache

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

Кэш компонента

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

Кэш страницы

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

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

5 голосов
/ 14 февраля 2009

Мне известны два значения.


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

Это "кеширование", которое вы используете здесь, когда цитируете:

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


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

Это "кеширование", которое вы используете здесь, когда цитируете:

Когда кто-то говорит, что он нашел кусок кода, который повредил бы кеширование, и после того, как он это исправил, это улучшило скорость их приложения, о чем они говорят?

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


Что касается кэширования базы данных , я не знаю.

4 голосов
/ 14 февраля 2009

Есть пара вопросов.

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

Другое дело, что приложение может хранить данные в своем «родном» формате, тогда как БД, очевидно, кэширует только во внутреннем формате.

Простой пример.

Скажем, у вас есть пользователь в базе данных, которая состоит из столбцов: USERID, FIRSTNAME, LASTNAME. Очень просто.

Вы хотите загрузить пользователя USERID=123 в ваше приложение. Какие шаги предпринимаются?

  1. Выдача вызова базы данных
  2. Разбор запроса (SELECT * FROM USER WHERE USERID = ?)
  3. Планирование запроса (т. Е. Как система собирается получать данные)
  4. Извлечение данных с диска
  5. Потоковая передача данных из базы данных в приложение
  6. Преобразование данных базы данных в данные приложения (то есть USERID в целое число, скажем, имена в строки.

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

Итак, вот ключ. Ваш пользователь, USER ID 123, имя JESSE JAMES. Вы можете видеть, что это не много данных. Но база данных кеширует дисковые блоки. У вас есть индексный блок (с 123 на нем), затем блок данных (с фактическими данными и всеми другими строками, которые умещаются в этом блоке). Итак, что номинально, скажем, 60-70 байт данных на самом деле имеет кеширование и влияние данных на БД, вероятно, 4K-16K (зависит от размера блока).

Светлая сторона? Если вам нужна другая строка, которая находится рядом (скажем, USER ID = 124), шансы высоки, индекс и данные уже кэшированы.

Но даже с этим кешированием вам все равно придется платить за перемещение данных по проводам (и это всегда по проводам, если вы не используете локальную БД, тогда это зацикливание), и вы «неустрашимы» " данные. То есть преобразование его из битов базы данных в биты языка в биты приложения.

Теперь, когда приложение получает USER ID 123, оно помещает значение в долгоживущую хэш-карту.

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

Темная сторона кэширования приложений - синхронизация. Если кто-то входит и делает UPDATE USER SET LASTNAME="SMITH" WHERE USERID=123, ваше приложение не «знает об этом», и, следовательно, кэш грязный.

Итак, есть множество деталей в обработке этих отношений для синхронизации приложения с БД.

Наличие большого количества кэша базы данных очень удобно для больших запросов к «горячему» набору данных. Чем больше у вас памяти, тем больше «горячих» данных вы можете иметь. Вплоть до того, что вы можете кэшировать всю БД в ОЗУ, вы устраняете задержку ввода-вывода (по крайней мере, для чтения) перемещения данных с диска в буфер ОЗУ. Но у вас все еще есть расходы на транспорт и сортировку.

Приложение может быть гораздо более избирательным, например, кешировать более ограниченные подмножества данных (БД - это просто блоки кеша), а расположение данных «ближе» к приложению повышает эту производительность.

Недостатком является то, что не все кэшируется в приложении. База данных, как правило, хранит данные более эффективно, чем приложение. Вам также не хватает языка «запросов» для кэшированных данных вашего приложения. Большинство людей просто кешируют с помощью простого ключа и переходят оттуда. Легко найти USER ID 123, сложнее для "ВСЕХ ПОЛЬЗОВАТЕЛЕЙ ИМЯ ДЖЕССА".

Кэширование базы данных имеет тенденцию быть «свободным», вы устанавливаете номер буфера, а СУБД обрабатывает все остальное. Низкое влияние, уменьшает общие затраты ввода-вывода и задержки диска.

Кэширование приложения, в частности, зависит от приложения.

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

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

Все это сводится к тому, что до тех пор, пока у вас есть API данных, вы можете кэшировать его постепенно.

Итак, до тех пор, пока вы вызываете getUser(123) везде, а не нажимаете на БД, вы можете позже вернуться и добавить кеширование в getUser без ущерба для вашего кода.

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

2 голосов
/ 14 февраля 2009

Понятие кеша здесь перегружено. Я не знаком с особенностями кэширования базы данных.

В приложениях есть два использования термина.

Когда кто-то говорит, что нашел кусок кода, который повредил бы кеширование и после того, как они исправили это, он улучшился скорость их приложения, что они о чем?

В этом случае они ссылаются на кэш процессора.

Кэш-память процессора - это встроенная память процессора, которая намного быстрее оперативной памяти, но не имеет произвольного доступа. То, что процессор решает загрузить в кеш, может немного усложниться. См. Ульрих Дрепперс Что каждый программист должен знать о памяти , чтобы узнать больше.

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

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

На эффективность использования кеша могут влиять разные вещи: прогноз ветвления для кода, загруженного в кеш, размер и выравнивание структур данных и шаблонов доступа, где и когда объявлять локальные переменные, которые будут помещены в стек.

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

2 голосов
/ 14 февраля 2009

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

1 голос
/ 14 февраля 2009

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

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

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

http://www.danga.com/memcached/

Примером определенного типа кэширования может быть кэширование asp.net. Asp.net поддерживает несколько видов кеша. Существует традиционный объектный кеш (который можно использовать во всех видах приложений .net, а не только на веб-сайтах). Существуют также функции кэширования, которые позволяют настраивать страницы и пользовательские элементы управления для автоматического кэширования их вывода. Он не кэширует данные, он кэширует конечный результат (HTML-код страницы) и обрабатывает его, когда пользователь запрашивает ту же страницу с теми же параметрами строки запроса, что и предыдущий пользователь.

0 голосов
/ 14 февраля 2009

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

function f(n)
    if n < 2 then
        return n;
    return f(n - 1) + f(n - 2)

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

fib_cache = {}

function f(n)
    if n < 2 then
        return n;
    if fib_cache.contains(n) then
        return fib_cache[n]
    fib_cache[n] = f(n - 1) + f(n - 2)
    return fib_cache[n]
0 голосов
/ 14 февраля 2009

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

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

Есть много способов сделать это, но сама концепция тривиальна.

Редактировать: Это можно сделать и на ЛЮБОМ уровне - все, что занимает много времени, может быть кэшировано где-то, к чему вы можете добраться быстрее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...