Использование нескольких экземпляров MemoryCache

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

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

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

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

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

Ответ 1

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

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

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

from Свойство MemoryCache.CacheMemoryLimit

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

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

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

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

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

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

Ответ 2

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

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