bit*_*ops 6 ruby multithreading ruby-on-rails race-condition
我试图race_condition_ttl在使用Rails.cache.fetch.
我有一个如下所示的控制器操作:
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
Run Code Online (Sandbox Code Playgroud)
根据我在 Rails 文档中阅读的内容,该值应在 30 秒后过期,但允许再提供 60 秒的陈旧值。但是,我无法弄清楚如何重现将显示此行为有效的条件。这是我尝试测试它的方式。
100.times.map do
t = Thread.new { RestClient.get("http://myenvironment/foo") }
t
end.map {|t| t.join.value }.uniq
Run Code Online (Sandbox Code Playgroud)
我的 Rails 应用程序在标准 nginx/unicorn 设置后面的 VM 上运行。我正在尝试同时生成 100 个线程来模拟“狗堆效应”。但是,当我运行我的测试代码时,所有线程都返回相同的值。我希望看到的是,一个线程获得了新值,而至少另一个线程获得了一些陈旧的内容。
欢迎任何指点!非常感谢。
您设置race_condition_ttl为 60 秒,这意味着您的线程只会在此时间到期后才开始获取新值,甚至不考虑最初的 30 秒。
您的测试看起来不像是运行 1.5 分钟,这是线程开始获取新值所必需的。从Rails 缓存文档:
是的,此过程将过时值的时间再延长几秒钟。由于先前缓存的使用寿命延长,其他进程将继续使用稍微过时的数据一段时间。
文本暗示使用小号race_condition_ttl,这对于其目的和您的测试来说都是有意义的。
更新
另请注意,仅当它最近过期时,陈旧缓存的生命周期才会延长。否则会生成一个新值并且 :race_condition_ttl 不起作用。
如果没有阅读源代码,Rails 如何决定它的服务器何时受到攻击或者recently上面引用中的确切含义并不是特别清楚。尽管等待访问缓存的第一个进程(许多)在延长前一个的生命周期的同时设置新值,但似乎很清楚。等待进程的存在可能是 Rails 寻找的条件。在任何情况下,都应该在初始超时和 ttl 到期并且缓存开始提供更新的值后观察预期的行为。初始超时和新值开始显示之间的延迟应该与 ttl.conf 类似。当然前提是服务器应该在初始超时到期的那一刻被锤击。