Rails.cache相关知识
可能里面的一些知识已经不被大家使用了,但是作为学习,我想和大家分享一下个人关于rails.cache的浅显的认识,望大家指教。
1.rails.cache是什么
它是rails中的缓存,拥有所有缓存的共同点,它是为了提升网站性能。
2.rails中rails.cache的存储系统。
本身常用的有四种,可以根据不同的环境进行选择不同的存储系统。
- filestore,利用文件系统缓存文件,能够在多个应用间共享缓存,但是这样会不断的增加硬盘使用。
- memorystore, ruby 进程使用共同的内存,默认大小为32m,,虽然可以更改这个限制,但是不适合大型的部署,并且它不能用于多个应用共享缓存。
- memcachestore, 这种方式使用 memcached 最为后端缓存服务,它提供了高性能的、集中式的缓存服务,可以在多个应用间共享缓存,这是一种适合中大型商业应用的选择。
- nullstore, 适合开发和测试环境的配置,它不会储存任何东西,但是可以正常调试 rails.cache 中的方法。
3. rails项目的自定义配置存储系统。
这里我以使用redis来作为rails.cache的存储系统进行介绍
3.1 为什么会选redis
因为是key-value的结构,同时使用redis,能够通过 redis 的命令快速实现,比关系型数据库拥有更快的读写速度,且更适合储存非结构化数据。
3.2 如何配置
- 确保你的系统已经安装了redis数据库(具体怎么安装,这里不做阐述)
- 在你的gemfile文件中,加入gem 'redis-rails'这一行,然后bundle install。
- 一般初始化的默认配置可以在development.rb,production.rb,test.rb文件中单独设置适用于不同环境的存储系统;我选择直接在application.rb中写配置信息。
配置信息(必须): config.action_controller.perform_caching = true # 确保开启缓存,dev环境下默认是没有开启的。 config.cache_store = :redis_store, { host: 'localhost', port: '6379', db: 1, # 这是整数,可以理解为redis数据库中的表标志,默认是16个数据库,可从0-15中取值 password: '', expires_in: 5.hours # 过期时间的设置 }
4. rails.cache常见用法。
4.1 首先如何设置开启缓存
production上默认开启了缓存
-
development上默认不开启
配置方法一(常用):
# 在development.rb文件中添加 config.action_controller.perform_caching = true # 设置缓存的页面存放的地址(不能修改,默认是public) config.action_controller.page_cache_directory = "#{rails.root.to_s}/public"
配置方法二(rails5版本之后开始支持):
# 执行任务,会在tmp文件下创建caching-dev.txt和restart.txt文件 rake dev:cache
经过个人测试,两者不能混用,混用存在的问题:
1.如果你使用rake dev:cache,就不能在development.rb中去修改缓存默认存储的地址,一旦修改,缓存就会失效。
2.一旦你是用rake dev:cache来开启缓存,那么就要使用rake dev:cache来关闭缓存(不能通过config.action_controller.perform_caching = false来操作,无法起作用),如果要自己测试,那你一定要首先把之前缓存的文件给删除掉,不然不管你怎么操作,只要public下有该文件,就一直读该文件。如果看一下rake dev:cache的源码,我们能找到另外一种方式来关闭
# 源码 rake任务 namespace :dev do desc "toggle development mode caching on/off" task :cache do rails::devcaching.enable_by_file end end # 源码:通过文件来判断是否开启缓存 file = "tmp/caching-dev.txt" def enable_by_file fileutils.mkdir_p("tmp") if file.exist?(file) delete_cache_file puts "development mode is no longer being cached." else create_cache_file puts "development mode is now being cached." end fileutils.touch "tmp/restart.txt" end
所以,很明显,我们可以通过删除tmp下的restart.txt和cache-dev.txt来关闭缓存。
个人建议:还是在development.rb文件中自己配置比较灵活
4.2 如何使用3种缓存方式(片段缓存,页面缓存,方法缓存),从rails4开始,页面缓存和方法缓存已经转换为gem的形式,只有片段缓存是rails默认的。
-
页面缓存
一句话总结:使用缓存的页面来代替action请求对应的页面,这个和缓存系统无关。
默认缓存的文件直接放在public目录下。页面缓存现在已经被单独作为一个gem,需要在你的gemfile中加入 gem "actionpack-page_caching"
真正的代码实现:
# 一个控制器 class huancuncontroller < applicationcontroller # 使用缓存 caches_page :welcome_show # 缓存的页面对应的控制器 def welcome_show end end
welcome_show页面
hello,welcom!!
current_time_now:<%= time.now.strftime('%y-%m-%d %h:%m:%s.%l') %>没有使用缓存的时候,每次请求的页面都是实时变化的,可以看current_time_now的值。
使用缓存后,会在你配置保存目录的文件下生成对应的静态html文件。 -
方法缓存
在gemfile文件中加入gem 'actionpack-action_caching'
为了便于观察,选择redis作为缓存系统。使用方法缓存的代码如下: class car::carscontroller < applicationcontroller caches_action :index def index end end
监控方法:
打开终端,输入redis-cli,然后输入monitor,可以监控redis的存储情况。
调用该index方法,会产生一个key:"get""views/locahost:3003/car/cars"以后每次再去调用该index,你会发现redis的monitor中都是显示如下信息:说明缓存成功,不再每次去方法中执行,而是直接从redis中去取。
1560408837.780396 [2 [::1]:54380] "get" "views/localhost:3003/car/cars" 1560408838.140465 [2 [::1]:54380] "get" "views/localhost:3003/car/cars" 1560408838.667096 [2 [::1]:54380] "get" "views/localhost:3003/car/cars"
过期时间的问题:
如果你没有设置过期时间,那么他的过期时间使用redis设置的过期时间。
如果想查看过期时间,进入redis控制台,然后选择你使用的数据库id,例如(查出来的时间是以秒为单位)
mymacbook-pro redis-cli 127.0.0.1:6379>select 2 ok 127.0.0.1:6379[2]> ttl "views/localhost:3003/car/cars" (integer) 13620 127.0.0.1:6379[2]>=
如果想自己设置过期时间,可以直接查看gem 'actionpack-action_caching'这个gem的文档 -
片段缓存
片段缓存是rails中最常用的一种缓存方式,主要是在页面中进行局部缓存。在index.html.erb页面中 <% cache 'test_index' do %> <%= time.now.strftime('%y-%m-%d %h:%m:%s.%l') %> <% end %>
这个其实和方法缓存的监控的方式一样,你会发现会生成"views/car/cars/index:61696bc621e5ee68531c6a58dfaf4da3/test_index"这样的key,同时也能查到过期时间。
每次你去刷新页面,都会在redis中去请求这个key值对应的value值。
如果想自己设置过期时间为2小时,可以这样设置<% cache 'test_index',expires_in: 2.hours do %> <%= time.now.strftime('%y-%m-%d %h:%m:%s.%l') %> <% end %>
如果你想让这个"views/car/cars/index:61696bc621e5ee68531c6a58dfaf4da3/test_index"的key失效,你可以使用expire_fragment('views/car/cars/index:61696bc621e5ee68531c6a58dfaf4da3/test_index') ,但是在实际应用中我们无法查到这个key的具体值,所以我们可以这样设置:
<% cache 'test_index', {skip_digest: true} do %> <%= time.now.strftime('%y-%m-%d %h:%m:%s.%l') %> <% end %>
这样’test_index’将会被作为cache key被缓存起来,如果想要使他失效,只要在对应的action里调用就expire_fragment('test_index')就行,如果不加 {skip_digest: true},那么是无法直接调用expire_fragment('test_index')的。
可以简单的查看一下生成这个片段name的源码:def cache_fragment_name(name = {}, skip_digest: nil, virtual_path: nil) if skip_digest name else fragment_name_with_digest(name, virtual_path) end end 可以很明显的看出,如果skip_digest是true,将直接返回页面中写的name。