Зачем использовать кеш на уровне приложения, если база данных уже обеспечивает кеширование? - PullRequest
23 голосов
/ 03 июня 2010

Современная база данных обеспечивает поддержку кэширования. Большинство фреймворков ORM также кэшируют извлеченные данные. Почему это дублирование необходимо?

Ответы [ 8 ]

34 голосов
/ 03 июня 2010

Поскольку для получения данных из кэша базы данных вам все равно необходимо:

  1. Генерация SQL из "собственного" формата запроса ORM
  2. Выполнение сетевого обхода на сервере базы данных
  3. Разбор SQL
  4. Получить данные из кеша
  5. Сериализация данных в проводном формате базы данных
  6. Десериализация данных в формат клиентской библиотеки базы данных
  7. Преобразование формата клиентской библиотеки базы данных в объекты языкового уровня (т. Е. Набор данных)

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

8 голосов
/ 03 июня 2010

Вот несколько причин, почему вы можете захотеть это:

  • Приложение кэширует только то, что ему нужно, поэтому вы должны получить лучший коэффициент попадания в кэш
  • Доступ к локальному кэшу, вероятно, будет на пару порядков быстрее, чем доступ к базе данных из-за задержек в сети - даже при быстрой сети
6 голосов
/ 03 июня 2010

Правильно указаны требования к производительности, связанные с обходами сети.

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

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

Учитывайте это каждый раз, когда важны точность и последовательность.

6 голосов
/ 03 июня 2010

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

Платформа ORM работает в том же пространстве, что и ваше приложение. Так что туда и обратно нет. Это просто доступ к памяти, который обычно намного быстрее.

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

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

5 голосов
/ 03 июня 2010

Кроме того, кэш базы данных может быть не таким практичным, как кажется. Я скопировал это из http://highscalability.com/bunch-great-strategies-using-memcached-and-mysql-better-together - это специфично для MySQL, хотя.

Учитывая, что в MySQL есть кеш, зачем вообще нужен memcached?

Кэш MySQL связан только с одним экземпляром. Это ограничивает кэш-память максимальным адресом одного сервера. Если ваша система больше, чем память для одного сервера, то использование кэша MySQL не будет работать. И если тот же объект читается из другого экземпляра, он не кэшируется.

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

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

4 голосов
/ 05 июня 2010

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

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

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

3 голосов
/ 05 июня 2010

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

2 голосов
/ 08 июня 2011

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

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

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

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

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

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

...