Ответ 1
Да, вы можете сделать это с помощью Rails. Вам нужно создать второй кеш и сделать его доступным в приложении как глобальную переменную, а затем вызвать соответствующий кеш в зависимости от контекста. Каждому кешу присваивается свой собственный блок памяти (по умолчанию 32 МБ), и если один кеш заполняется, это не повлияет на другой кеш. Это делается с помощью ActiveSupport::Cache::MemoryStore.new
.
Я продемонстрирую, что два кэша не влияют друг на друга:
Сначала создайте два текстовых файла, которые будут использоваться для проверки кеша, один 10 МБ и один 30 МБ:
dd if=/dev/zero of=10M bs=1m count=10
dd if=/dev/zero of=30M bs=1m count=30
Откройте консоль Rails и прочитайте ее в строки:
ten = File.read("10M"); 0
thirty = File.read("30M"); 0
Хранить ten
в кеше:
Rails.cache.fetch("ten") { ten }; 0
Подтвердите, что данные были кешированы:
Rails.cache.fetch("ten")[0..10]
=> "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"
Хранить thirty
в кеше:
Rails.cache.fetch("thirty") { thirty }; 0
Подтвердите, что это не было сохранено (слишком большое для сохранения в кеше при расширении в виде строки):
Rails.cache.fetch("thirty")[0..10]
NoMethodError: undefined method `[]' for nil:NilClass
Подтвердите, что вы исчерпали весь кеш:
Rails.cache.fetch("ten")[0..10]
NoMethodError: undefined method `[]' for nil:NilClass
Теперь создайте второй кеш и подтвердите, что он ведет себя идентично исходному кешу:
store = ActiveSupport::Cache::MemoryStore.new
store.fetch("ten") { ten }; 0
store.fetch("ten")[0..10]
=> "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"
store.fetch("thirty") { thirty }; 0
store.fetch("thirty")[0..10]
NoMethodError: undefined method `[]' for nil:NilClass
store.fetch("ten")[0..10]
NoMethodError: undefined method `[]' for nil:NilClass
Теперь есть два пустых кеша: store
и Rails.cache
. Пусть подтверждают, что они независимы:
Rails.cache.fetch("ten") { ten }; 0
Rails.cache.fetch("ten")[0..10]
=> "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"
store.fetch("thirty") { thirty }; 0 # bust the `store' cache
Rails.cache.fetch("ten")[0..10]
=> "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"
Если два кэша вмешались, то последний вызов store.fetch
разобьет оба кэша. Это только busts store
.
Чтобы реализовать второй кеш в своем приложении, создайте инициализатор config/initializers/cache.rb
и добавьте:
$cache = ActiveSupport::Cache::MemoryStore.new
Вызовите новый кеш в свой код так же, как и Rails.cache
:
$cache.fetch("foo") { "bar" }
Некоторые из этих деталей были взяты из этого ответа. Новый кеш поддерживает дополнительные параметры; проверьте MemoryStore и Кэширование с помощью Rails для более информацию о настройке кеша.
Это решение будет работать для небольших приложений. Обратите внимание на этот комментарий из MemoryStore docs:
Если вы запускаете несколько процессов сервера Ruby on Rails (что имеет место, если вы используете mongrel_cluster или Phusion Passenger), это означает, что экземпляры процесса сервера Rails не смогут совместно использовать данные кэша и это может быть не самый подходящий кэш в этом сценарии.