Rails 缓存值 lost/nil 尽管 expires_in 24.hours
Rails cached value lost/nil despite expires_in 24.hours
我正在使用 ruby 2.3.3 和 Rails 4.2.8 和 Puma(1 个工作人员,5 个线程),在我的管理(即不重要)页面上我想显示一些统计信息(整数值)来自我的数据库。有些请求需要很长时间才能执行,所以我决定缓存这些值并使用 rake 任务每天重写它们。
Admin#index 控制器
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#index view
<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
我遇到的问题是缓存的值几乎立即从缓存中消失,而且间歇性消失。在我试过的控制台中:
- 我Rails.cache.write一个值(例如product_a)一分钟后查看,它还在。虽然很粗糙,但我可以在 Memcachier 管理工具中看到 "Set cmds" 递增 1。
- 但是,当我添加下一个值(例如 product_b)时,第一个值消失了(变为零)!有时,如果我将所有 4 个值相加,2 似乎会保留下来。这些并不总是相同的值。就像打地鼠一样!
- 如果我 运行 rake 写入值然后尝试读取值,通常只留下两个值,而其他值丢失。
我看到过一个与此相关的类似问题,其中解释的原因是使用了多线程服务器。缓存的值保存在一个线程中,无法在另一个线程中访问,解决方案是使用内存缓存,我就是这样做的。
不仅仅是控制台。如果我只是重新加载 admin#index 视图来存储值或 运行 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 的证据。
我在这里错过了什么?为什么这些值不会保留在我的缓存中?
Heroku DevCenter 声明了一些不同的缓存配置,并给出了一些关于线程化 Rails 应用程序服务器的建议,例如 Puma
使用 connection_pool
gem:
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
}
我正在使用 ruby 2.3.3 和 Rails 4.2.8 和 Puma(1 个工作人员,5 个线程),在我的管理(即不重要)页面上我想显示一些统计信息(整数值)来自我的数据库。有些请求需要很长时间才能执行,所以我决定缓存这些值并使用 rake 任务每天重写它们。
Admin#index 控制器
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#index view
<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
我遇到的问题是缓存的值几乎立即从缓存中消失,而且间歇性消失。在我试过的控制台中:
- 我Rails.cache.write一个值(例如product_a)一分钟后查看,它还在。虽然很粗糙,但我可以在 Memcachier 管理工具中看到 "Set cmds" 递增 1。
- 但是,当我添加下一个值(例如 product_b)时,第一个值消失了(变为零)!有时,如果我将所有 4 个值相加,2 似乎会保留下来。这些并不总是相同的值。就像打地鼠一样!
- 如果我 运行 rake 写入值然后尝试读取值,通常只留下两个值,而其他值丢失。
我看到过一个与此相关的类似问题,其中解释的原因是使用了多线程服务器。缓存的值保存在一个线程中,无法在另一个线程中访问,解决方案是使用内存缓存,我就是这样做的。
不仅仅是控制台。如果我只是重新加载 admin#index 视图来存储值或 运行 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 的证据。
我在这里错过了什么?为什么这些值不会保留在我的缓存中?
Heroku DevCenter 声明了一些不同的缓存配置,并给出了一些关于线程化 Rails 应用程序服务器的建议,例如 Puma
使用 connection_pool
gem:
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
}