Использование нескольких экземпляров MemoryCache - PullRequest
67 голосов
/ 11 декабря 2011

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

Однако я вижу здесь , что использование более одного экземпляра MemoryCache не рекомендуется:

MemoryCache не является одноэлементным, но вы должны создать только несколько или, возможно, только один экземпляр MemoryCache, и код, который кэширует элементы, должен использовать эти экземпляры.

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

РЕДАКТИРОВАТЬ: В частности, у меня есть класс, который должен хранить кэш для каждого экземпляра. Следует ли мне избегать использования MemoryCache и искать другое решение для кэширования? Считается ли использование MemoryCache в этой ситуации плохим, и если да, то почему?

Ответы [ 2 ]

65 голосов
/ 17 ноября 2012

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

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

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

из Свойство MemoryCache.CacheMemoryLimit

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

Это особенно чувствительно в приложениях, которым не хватает роскоши выделенного сервера. Представьте, что вы запускаете свое приложение на общем сервере, где вам выделено только 150 МБ ОЗУ (обычный дешевый хостинг за 10 долларов в месяц), вам нужно рассчитывать на кэш, чтобы максимально использовать его, не превышая его. Если вы превысите это использование памяти, ваш пул приложений будет переработан, а ваше приложение потеряет все в кэш-памяти! (распространенная практика дешевого хостинга) То же самое можно применить к не веб-приложениям, размещенным дома на каком-либо общем корпоративном сервере. То же самое, вам сказали не загружать всю память на этом компьютере и мирно сосуществовать с другими бизнес-приложениями.

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

Я знаю, что MemoryCache - это не зависящая от веб-версии версия реализации System.Web.Caching.Cache, но это иллюстрирует логику реализации кэша. Та же логика может применяться в не-веб-проекте, если у вас нет эксклюзивного использования оборудования. Помните, что если ваш кеш вынуждает машину начать делать подкачки файлов подкачки, то ваш кеш больше не работает быстрее, чем кеширование на диске. Вы всегда будете хотеть где-нибудь ограничение, даже если это ограничение 2 ГБ или что-то.

В моем случае после прочтения об этом я переключился на использование одного «публичного статического MemoryCache» в своем приложении и просто сегментировал кэшированные элементы по их ключам кеша. Например, если вы хотите кэшировать для каждого экземпляра, вы можете иметь ключ кэширования, например, «instance- {instanceId} -resourceName- {resourceId}». Думайте об этом как об именах интервалов между записями в кэше.

Надеюсь, это поможет!

6 голосов
/ 23 августа 2012

Я тоже использую несколько.Обычно по одному на тип.

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

...