Rails кэширует значение потеряно / ноль, несмотря на expires_in 24.hours

Я использую Ruby 2.3.3 и Rails 4.2.8 с Puma (1 рабочий, 5 потоков), и на моей странице администратора (т.е. не критично) я хочу показать некоторую статистику (целочисленные значения) из моей базы данных. Некоторые запросы выполняются довольно долго, поэтому я решил кэшировать эти значения и использовать задачу rake, чтобы перезаписывать их каждый день.

Admin# контроллер индекса

require 'timeout'
begin
  timeout(8) do
    @products_a = Rails.cache.fetch('products_a', :expires_in => 24.hours) { Product.where(heavy_condition_a).size }

    @products_b = Rails.cache.fetch('products_b', :expires_in => 24.hours) { Product.where(heavy_condition_b).size }
    @products_c = Rails.cache.fetch('products_c', :expires_in => 24.hours) { Product.where(heavy_condition_c).size }
    @products_d = Rails.cache.fetch('products_d', :expires_in => 24.hours) { Product.where(heavy_condition_d).size }              
  end
rescue Timeout::Error
  @products_a = 999
  @products_b = 999
  @products_c = 999
  @products_d = 999   

end

Admin# просмотр индекса

    <li>Products A: <%= @products_a %></li>
    <li>Products B: <%= @products_b %></li>
    <li>Products C: <%= @products_c %></li>
    <li>Products D: <%= @products_d %></li>

Рейк задача

task :set_admin_index_stats => :environment do
    Rails.cache.write('products_a', Product.where(heavy_condition_a).size, :expires_in => 24.hours)
    Rails.cache.write('products_b', Product.where(heavy_condition_b).size, :expires_in => 24.hours)
    Rails.cache.write('products_c', Product.where(heavy_condition_c).size, :expires_in => 24.hours)
    Rails.cache.write('products_d', Product.where(heavy_condition_d).size, :expires_in => 24.hours)                     
end

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

production.rb

config.cache_store = :dalli_store

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

  1. Я Rails.cache. Записываю одно значение (например, product_a) и проверяю его через минуту, оно все еще там. Хотя это и грубо, я могу видеть приращение "Set cmds" на единицу в инструменте администрирования Memcachier.
  2. Однако, когда я добавляю следующее значение (например, product_b), первое исчезает (становится нулем)! Иногда, если я складываю все 4 значения, кажется, что 2 прилипают. Это не всегда одни и те же ценности. Это похоже на удар крота!
  3. Если я запускаю грабли для записи значений, а затем пытаюсь прочитать значения, обычно остается только два значения, тогда как остальные теряются.

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

Это не только консоль. Если я просто перезагружу admin # index view, чтобы сохранить значения или запустить задачу rake, я столкнусь с той же проблемой. Ценности не приживаются.

Я подозреваю, что я либо неправильно использую команды Rails.cache, либо эти команды на самом деле не используют Memcachier. Мне не удалось определить, действительно ли мои значения хранятся в Memcachier, но когда я использую свою первую команду в консоли, я получаю следующее:

Rails.cache.read('products_a')
Dalli::Server#connect mc1.dev.eu.ec2.memcachier.com:11211
Dalli/SASL authenticating as abc123
Dalli/SASL authenticating as abc123
Dalli/SASL: abc123
Dalli/SASL: abc123
=> 0

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

Что мне здесь не хватает? Почему значения не остаются в моем кеше?

1 ответ

Решение

Heroku DevCenter заявляет немного другую конфигурацию кеша и дает несколько советов по многопоточным серверам приложений Rails, напримерPuma с помощью connection_pool драгоценный камень:

config.cache_store = :mem_cache_store,
  (ENV["MEMCACHIER_SERVERS"] || "").split(","),
  { :username => ENV["MEMCACHIER_USERNAME"],
    :password => ENV["MEMCACHIER_PASSWORD"],
    :failover => true,
    :socket_timeout => 1.5,
    :socket_failure_delay => 0.2,
    :down_retry_delay => 60,
    :pool_size => 5
  }
Другие вопросы по тегам