是的,您可以使用 Rails 做到这一点。您需要创建第二个缓存并将其作为全局变量在您的应用程序中可用,然后根据上下文调用适当的缓存。每个缓存都分配有自己的内存块(默认为 32 MB),如果一个缓存已满,则不会影响另一个缓存。这是通过ActiveSupport::Cache::MemoryStore.new 完成的。
我将证明这两个缓存不会相互影响:
首先,生成两个用于测试缓存的文本文件,一个 10 MB 和一个 30 MB:
dd if=/dev/zero of=10M bs=1m count=10
dd if=/dev/zero of=30M bs=1m count=30
打开 Rails 控制台并将这些读入字符串:
ten = File.read("10M"); 0
thirty = File.read("30M"); 0
在缓存中存储ten:
Rails.cache.fetch("ten") { ten }; 0
确认数据已缓存:
Rails.cache.fetch("ten")[0..10]
=> "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"
在缓存中存储thirty:
Rails.cache.fetch("thirty") { thirty }; 0
确认没有保存(展开为字符串时太大而无法保存在缓存中):
Rails.cache.fetch("thirty")[0..10]
NoMethodError: undefined method `[]' for nil:NilClass
确认这已经破坏了整个缓存:
Rails.cache.fetch("ten")[0..10]
NoMethodError: undefined method `[]' for nil:NilClass
现在创建第二个缓存并确认它的行为与原始缓存相同:
store = ActiveSupport::Cache::MemoryStore.new
store.fetch("ten") { ten }; 0
store.fetch("ten")[0..10]
=> "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"
store.fetch("thirty") { thirty }; 0
store.fetch("thirty")[0..10]
NoMethodError: undefined method `[]' for nil:NilClass
store.fetch("ten")[0..10]
NoMethodError: undefined method `[]' for nil:NilClass
现在有两个空缓存:store 和 Rails.cache。让我们确认它们是独立的:
Rails.cache.fetch("ten") { ten }; 0
Rails.cache.fetch("ten")[0..10]
=> "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"
store.fetch("thirty") { thirty }; 0 # bust the `store' cache
Rails.cache.fetch("ten")[0..10]
=> "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"
如果两个缓存相互干扰,那么最后一个store.fetch 调用将破坏两个缓存。它只会破坏store。
要在您的应用中实现第二个缓存,请创建一个初始化器 config/initializers/cache.rb 并添加:
$cache = ActiveSupport::Cache::MemoryStore.new
在代码中调用新缓存的方式与 Rails.cache 相同:
$cache.fetch("foo") { "bar" }
其中一些细节来自this answer。新的缓存支持附加选项;查看MemoryStore 和Caching with Rails 了解有关自定义缓存的更多信息。
此解决方案适用于小型应用。请注意 MemoryStore 文档中的这条评论:
如果您正在运行多个 Ruby on Rails 服务器进程(如果您使用的是 mongrel_cluster 或 Phusion Passenger),那么这意味着 Rails 服务器进程实例将无法相互共享缓存数据在这种情况下,这可能不是最合适的缓存。