我目前正在考虑提高Rails.cache.write
使用 dalli 将项目写入memcachier云时的性能。
与缓存相关的堆栈当前为:
heroku, memcachier heroku addon, dalli 2.6.4, rails 3.0.19
我正在使用 newrelic 进行性能监控。
我目前正在为给定的登录用户获取“活跃的学生”,由一个BusinessUser
实例表示,当它的active_students
方法从处理需要“活跃学生”列表的请求的控制器调用时:
class BusinessUser < ActiveRecord::Base
...
def active_students
Rails.cache.fetch("/studio/#{self.id}/students") do
customer_users.active_by_name
end
end
...
end
在查看了 newrelic 之后,我基本上缩小了应用程序在 memcachier 上设置键值的一大性能影响。每次平均需要225ms。此外,设置 memcache 键值看起来会阻塞主线程并最终破坏请求队列。显然这是不可取的,尤其是当缓存策略的全部目的是减少性能瓶颈时。
此外,我用普通的 dalli 和 Rails.cache.write 对 1000 个相同值的缓存集对缓存存储进行了基准测试:
heroku run console -a {app-name-redacted}
irb(main):001:0> require 'dalli'
=> false
irb(main):002:0> cache = Dalli::Client.new(ENV["MEMCACHIER_SERVERS"].split(","),
irb(main):003:1* {:username => ENV["MEMCACHIER_USERNAME"],
irb(main):004:2* :password => ENV["MEMCACHIER_PASSWORD"],
irb(main):005:2* :failover => true,
irb(main):006:2* :socket_timeout => 1.5,
irb(main):007:2* :socket_failure_delay => 0.2
irb(main):008:2> })
=> #<Dalli::Client:0x00000006686ce8 @servers=["server-redacted:11211"], @options={:username=>"username-redacted", :password=>"password-redacted", :failover=>true, :socket_timeout=>1.5, :socket_failure_delay=>0.2}, @ring=nil>
irb(main):009:0> require 'benchmark'
=> false
irb(main):010:0> n = 1000
=> 1000
irb(main):011:0> Benchmark.bm do |x|
irb(main):012:1* x.report { n.times do ; cache.set("foo", "bar") ; end }
irb(main):013:1> x.report { n.times do ; Rails.cache.write("foo", "bar") ; end }
irb(main):014:1> end
user system total real
Dalli::Server#connect server-redacted:11211
Dalli/SASL authenticating as username-redacted
Dalli/SASL: username-redacted
0.090000 0.050000 0.140000 ( 2.066113)
Dalli::Server#connect server-redacted:11211
Dalli/SASL authenticating as username-redacted
Dalli/SASL: username-redacted
0.100000 0.070000 0.170000 ( 2.108364)
使用普通的 dalli cache.set
,我们使用 2.066113 秒将 1000 个条目写入缓存,平均cache.set
时间为 2.06 毫秒。
使用Rails.cache.write
,我们使用 2.108364 秒将 1000 个条目写入缓存,平均Rails.cache.write
时间为 2.11 毫秒。
⇒ 问题似乎不在于 memcachier,而在于我们试图存储的数据量。
根据#fetch method 的文档,如果我想将缓存集扔到单独的线程或工作人员中,这似乎不是我想要的方式,因为我无法write
从read
-不言而喻,我不想异步阅读。
Rails.cache.write
在设置键值时,是否可以通过投入工作人员来减少瓶颈?或者,更一般地说,是否有更好的模式来执行此操作,这样我就不会在每次想要执行时阻塞主线程Rails.cache.write
?