在 Rails 中了解 race_condition_ttl

Understanding race_condition_ttl in Rails

我试图在使用 Rails.cache.fetch 时理解 Rails 中的 race_condition_ttl 指令。

我有一个如下所示的控制器操作:

def foo
  @foo = Rails.cache.fetch("foo-testing", expires_in: 30.seconds, race_condition_ttl: 60.seconds) do
      Time.now.to_s
  end
  @foo # this gets used in a view down the line...
end

根据我在 Rails 文档中阅读的内容,此值应在 30 秒后过期,但允许过时值再提供 60 秒。但是,我无法弄清楚如何重现将向我展示这种行为有效的条件。这是我尝试测试它的方式。

100.times.map do 
  t = Thread.new { RestClient.get("http://myenvironment/foo") }
  t 
end.map {|t| t.join.value }.uniq

我的 Rails 应用程序 运行 在标准 nginx/unicorn 设置后的 VM 上运行。我正在尝试生成 100 个同时访问站点的线程来模拟 "dog pile effect"。但是,当我 运行 我的测试代码时,所有线程都报告相同的值。我希望看到的是一个线程获得新值,而 至少 另一个线程获得一些陈旧的内容。

欢迎大家指点!非常感谢。

您将 race_condition_ttl 设置为 60 秒,这意味着您的线程将仅在该时间到期后才开始获取新值,甚至不考虑最初的 30 秒。

您的测试看起来不像 运行 需要 1.5 分钟,这是线程开始获取新值所必需的。来自 Rails Cache docs:

Yes, this process is extending the time for a stale value by another few seconds. Because of extended life of the previous cache, other processes will continue to use slightly stale data for a just a bit longer.

文本暗示使用小 race_condition_ttl 并且它对它的目的和你的测试都有意义。

更新

Also note that the life of stale cache is extended only if it expired recently. Otherwise a new value is generated and :race_condition_ttl does not play any role.

如果不阅读源代码,就不会特别清楚 Rails 如何决定其服务器何时受到攻击,或者 recently 在上面的引述中究竟意味着什么。看起来很明显,等待访问缓存的进程中的第一个(许多)进程设置新值,同时延长前一个进程的寿命。等待进程的存在可能是 Rails 寻找的条件。在任何情况下,在初始超时和 ttl 过期并且缓存开始提供更新值后,都应该观察到预期的行为。初始超时和新值开始出现之间的延迟应该类似于 ttl.当然前提是服务器应该在初始超时到期的那一刻被锤击。