最近被 Rails 的缓存坑得有点惨,笔者只知道缓存要启动,却忘记缓存要合适才有意义。这篇文章简单聊聊Cache Stores。原文链接:https://step-by-step.tech/posts/cache-stores-in-rails
一般来说在开发环境并不需要打开缓存,只不过有时候为了调试缓存的线上效果,需要在开发环境打开缓存功能。开启的方式也很简单,直接本地运行命令bin/rails dev:cache
> bin/rails dev:cache
Development mode is now being cached.
> bin/rails dev:cache
Development mode is no longer being cached.
运行结果会提示你,开发模式是否已经开启了缓存。其实打开文件config/environments/development.rb
,可以看到这么一段代码
Rails.application.configure do
....
if Rails.root.join('tmp', 'caching-dev.txt').exist?
config.action_controller.perform_caching = true
config.action_controller.enable_fragment_cache_logging = true
config.cache_store = :memory_store
config.public_file_server.headers = {
'Cache-Control' => "public, max-age=#{2.days.to_i}"
}
else
config.action_controller.perform_caching = false
config.cache_store = :null_store
end
end
原理很简单,如果tmp/caching-dev.text
这个文件存在表示缓存已经开启,否则的话表示开发环境不开启缓存,所以你也可以通过命令
> touch tmp/caching-dev.txt
开启开发环境的缓存,再通过命令
> rm tmp/caching-dev.txt
来关闭开发环境的缓存,效果跟官方脚本是一样的。
从配置config.cache_store = :memory_store
可以看出,当前采用的 Cache Store 是memory_store
。具体文档可以看这里。也可以通过内省的方式查看
> Rails.cache
=> <#ActiveSupport::Cache::MemoryStore entries=0, size=0, options={}>
可见开发环境的缓存存储器是ActiveSupport::Cache::MemoryStore
对应了memory_store
,也就是把缓存内容存放在机器的内存里面。配置起来相对比较简单,毕竟每台机器都有内存资源,只要设置最大的存储区大小即可
config.cache_store = :memory_store, { size: 64.megabytes }
不需要别的额外配置。
这里说的线上环境,指的是生产环境或者预生产环境。一般这种环境的配置文件都跟config/environments/production.rb
有点类似,
关于缓存存储器的代码,都是注释掉的
Rails.application.configure do
# config.cache_store = :mem_cache_store
end
也就是都是采用缺省配置。然而笔者没想到的是原来缺省配置是file_store
。这是我在生产环境下内省得到的结果
> Rails.application.config.cache_store
=> [:file_store, "/www/project/huiliu-web/tmp/cache/"]
也就是说缓存结果会持久化到目录/www/huiliu/huiliu-web/tmp/cache/
中,笔者的上一篇文章提到的inode number
导致的空间不足,其实就是这个导致的。系统运行时间长,缓存持久化文件过多,且没有定时清理,导致inode number
耗尽。现在回想起来主要原因还是笔者没有用到合适的缓存存储器。
Rails 提供的缓存存储器主要是这几个,文档都有相应说明
自定义就是指可以根据自己的需求去实现缓存存储器的适配器。大伙可以根据自己的实际情况进行选择,不管怎么说,笔者强烈不建议使用file_store
,如果真的需要多台机器之间共享缓存,那么使用mem_cache_store
或者redis_cache_store
并购买相关的第三方服务可能是更好的选择。简单起见,在笔者现有的项目里面,使用memory_store
就好。因为笔者现在的机器内存还算是比较有盈余的,所以设置得大一点
Rails.application.configure do
config.cache_store = :memory_store, { size: 1024.megabytes } # 2048问题也不大
end
根据memory_store
的说法是,当缓存量超出设定的值的时候,会优先淘汰最久未被访问过的缓存数据。其实就是Least recently used (LRU)算法,原文是这样的
When the cache exceeds the allotted size, a cleanup will occur and the least recently used entries will be removed.
不一定一开始就上mem_cache_store
或者redis_cache_store
,有时候简单能用不失为一个更好的选择。
这篇文章简单聊了一下 Rails 服务里面的缓存存储器,这些引擎主要是针对部分的SQL Caching场景以及Page Caching场景的。这些缓存存储器各有千秋,根据自己的业务场景选择合适自己的就好。