Implementation of the cache system by Redis (vi)

Source: Internet
Author: User

1. Introduction

Rails comes with a cache feature, but it uses files to store data by default. We're going to use Redis to store it instead. And we also need to store the sessions in Redis. The source code for the cache feature of rails is visible in these places:

    • Https://github.com/rails/rails/blob/master/activesupport/lib/active_support/cache.rb
    • Https://github.com/rails/rails/tree/master/activesupport/lib/active_support/cache
    • Https://github.com/rails/rails/blob/master/actionview/lib/action_view/helpers/cache_helper.rb
2. Use

We use the cache in rails one step at a pace to meet our needs.

2.1 Turn on Cache mode

The first step is to start the cache mode. By default, the production environment is turned on, but development does not, so you have to turn it on.

Enter the config/environments/development.rb file and config.action_controller.perform_caching set to true.

config.action_controller.perform_caching = true

After modifying, remember to restart the server.

2.2 Using the HTML fragment cache

To facilitate testing and understanding of the whole principle, we will not use Redis to store the cache data, only the default file to hold the data.

Take this site as an example, we want to the homepage of the "recent article" that part plus the cache of HTML fragment.

Using HTML snippets Cache,rails provides a helper method that can be done simply by wrapping the required HTML with the cache.

.Row-CacheDo.Col-Md-6.Panel.Panel-Default.Panel-HeadingDiv recent article .-body - @articles .do | Article| p. Clearfix span. Pull-right = datetime article< Span class= "P". created_at = link_to article.< Span class= "NF" >titlearticle_path (article)                

Let's refresh the page first and then look through the logs.

First find that access is a little slower than usual, because it is in the cache to the file, the specific log is the following.

Started GET "/" for 127.0.0.1 in 2015-10-30 16:19:27 +0800processing by Homecontroller#index as HTML Cache Digest for App /views/home/index.html.slim:8e89c7a7d1da1d9719fca4639859b19dread Fragment views/localhost:4000// 8e89c7a7d1da1d9719fca4639859b19d (0.3MS) article Load (2.0ms) Select "Articles". " Title "," articles "." Created_at "," articles "." Published "," articles "." group_id "," articles "." Slug "," articles "." ID "from" articles "WHERE" articles "." Published "=" ORDER by ID DESC LIMIT [["Published", "T"]] Group Load (3.5ms) Select "Groups". * FROM "groups" wher E "groups". " ID "in (1, 5, 3, 4) article Load (0.9ms) Select" Articles "." Title "," articles "." Created_at "," articles "." Published "," articles "." group_id "," articles "." Slug "," articles "." ID "," articles "." Visit_count "from" articles "WHERE" articles "." Published "=" ORDER by Visit_count DESC LIMIT [["Published", "T"]] Group Load (2.3ms) Select "Groups". * FROM "Gro UPS "WHERE" groups "." ID "in (1, 3, 4) Group Load (4.4ms) Select "Groups". * FROM "groups" Write fragment views/localhost:4000//8e89c7a7d1da1d9719fca4639859b19d (41.7ms) ... 

The main is Cache digest , Read fragment and Write fragment part.

Cache digestis to produce a MD5 code, this code to identify the fragment of the HTML, it will be very useful, we later to elaborate.

Read fragmentis to read the HTML fragment (stored as a file), according to the previously generated MD5 identity, found that does not exist, will generate an HTML fragment coexist together, that is Write fragment .

By default, the resulting HTML fragment file is present in the/tmp/cache directory, as follows:

~/codes/rails365 (master) $ tree tmp/cache/tmp/cache/├── 20B│   └── 6F1│       └── views%2Flocalhost%3A4000%2F%2F8e89c7a7d1da1d9719fca4639859b19d

Open views%2Flocalhost%3A4000%2F%2F8e89c7a7d1da1d9719fca4639859b19d This file and you will find that the HTML fragment is stored in it.

Now we're going to refresh the page again and look at the log.

Started GET "/" for 127.0.0.1 at 2015-10-30 16:53:18 +0800Processing by HomeController#index as HTML  Cache digest for app/views/home/index.html.slim: 8e89c7a7d1da1d9719fca4639859b19dRead fragment views/localhost:4000//8e89c7a7d1da1d9719fca4639859b19d (0.3ms)...

Will find Write fragment no, and do not query the database, the data are taken from the HTML fragment cache.

It's not finished yet. We have to consider a question, is that when we change the data or HTML content, the cache will automatically update it?

2.3 Cache Digest

First, change the HTML fragment code itself.

We changed the "recent article" to "the latest article" and then we looked into whether it would work.

Finally, by looking at the log, the discovery is still generated Write fragment and the instructions are in effect.

What is this principle?

We found the source of the cache's helper method.

DefCache(Name={},Options={},&block) if controller respond_to?  (:p erform_caching) &&  Controller.safe_concat (fragment_for ( cache_fragment_name (name), options&block< Span class= "P")) else yield end nil end                

Find the key in cache_fragment_name this method, the following two methods are found in compliance.

DefCache_fragment_name(Name={},Skip_digest:Nil,Virtual_path:Nil)IfSkip_digestNameElseFragment_name_with_digest(Name,Virtual_path)EndEndDefFragment_name_with_digest(Name,Virtual_path)#:nodoc:Virtual_path|| =@virtual_pathIfVirtual_pathName=Controller.Url_for(Name). split (if name. Is_a?  (hash) digest = digestor. Digest name: virtual_pathfinder: lookup_contextdependencies: view_cache_ Dependencies [namedigest  Span class= "K" >else name endend      

The key is in fragment_name_with_digest this method, it will find the first parameter of the cache, and then use the content of this parameter to generate MD5 code, we have just changed the content of the HTML, that is, the parameters changed, MD5 naturally changed, MD5 a change will have to regenerate HTML fragments.

So the first parameter of the cache method is the key, and its content is the basis for judging the re-generation of HTML fragments.

After changing the HTML fragment code, the HTML fragment is regenerated, but what if we add a record to the articles? By trying to discover that the HTML fragment is not regenerated.

I'll pass @artilces as the first parameter to the cache method.

.Row-Cache@articlesDo.Col-Md-6.Panel.Panel-Default.Panel-HeadingDiv recent article .-body - @articles .do | Article| p. Clearfix span. Pull-right = datetime article< Span class= "P". created_at = link_to article.< Span class= "NF" >titlearticle_path (article)                

Discovery generated Write fragment , which indicates that it is possible for the page to take effect.

Cache Digest for App/views/home/index.html.slim:1c628fa3d96abde48627f8a6ef319c1cread fragment views/articles/ 15-20151027051837664089000/articles/14-20151030092311065810000/articles/13-20150929153356076334000/articles/ 12-20150929144255631082000/articles/11-20151027064325237540000/articles/10-20150929153421707840000/articles/ 9-20150929123736371074000/articles/8-20150929144346413579000/articles/7-20150929144324012954000/articles/ 6-20150929144359736164000/1C628FA3D96ABDE48627F8A6EF319C1C (0.1ms) Write fragment views/articles/ 15-20151027051837664089000/articles/14-20151030092311065810000/articles/13-20150929153356076334000/articles/ 12-20150929144255631082000/articles/11-20151027064325237540000/articles/10-20150929153421707840000/articles/ 9-20150929123736371074000/articles/8-20150929144346413579000/articles/7-20150929144324012954000/articles/ 6-20150929144359736164000/1C628FA3D96ABDE48627F8A6EF319C1C (75.9ms) article Load (2.6ms) Select "Articles". " Title "," articles "." Created_at "," articles "." Updated_at "," articles "." Published "," articles "." group_id "," articles "." Slug "," articles "." ID "," articles "." Visit_count "from" articles "WHERE" articles "." Published "=" ORDER by Visit_count DESC LIMIT [["Published", "T"]]

However, in addition, there are SQL statements generated, and every subsequent request has, even if the cache is hit, because @articles as the first parameter, its content is to be found through the database.

There is a solution to this: put @articles content in the cache, so that you do not have to find the database every time, and once the update or create data, let @articles expire or regenerate.

To facilitate testing, we first changed the storage of the cache to Redis to store the data.

Add the following two lines to the Gemfile file to execute bundle .

gem ‘redis-namespace‘gem ‘redis-rails‘

config/application.rbAdd the following line in the.

config.cache_store = :redis_store, {host: ‘127.0.0.1‘, port: 6379, namespace: "rails365"}

@articlesThe content to be obtained from Redis, mainly read the value of the health in Redis articles .

class HomeController < ApplicationController  def index @articles = Rails.cache.fetch "articles" do Article.except_body_with_default.order("id DESC").limit(10).to_a end endend

Create or generate a article record to invalidate the data for Redis.

  class admin:: Articlescontroller < admin::BaseController Span class= "P". def create  @article = article< Span class= "P". new (article_params) rails< Span class= "P". cache. "articles" .endend             

This can be refreshed more than two times, you will find no longer check the database, unless you add or modify the article (article).

End

Implementation of the cache system by Redis (vi)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.