<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 6. redis 實現 cache 系統實踐 #### 1. 介紹 rails中就自帶有cache功能,不過它默認是用文件來存儲數據的。我們要改為使用redis來存儲。而且我們也需要把sessions也存放到redis中。關于rails實現cache功能的源碼可見于這幾處: - [https://github.com/rails/rails/blob/master/activesupport/lib/active\_support/cache.rb](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/tree/master/activesupport/lib/active_support/cache) - [https://github.com/rails/rails/blob/master/actionview/lib/action\_view/helpers/cache\_helper.rb](https://github.com/rails/rails/blob/master/actionview/lib/action_view/helpers/cache_helper.rb) #### 2. 使用 我們一步步在rails中使用cache實現我們的需求。 ##### 2.1 開啟cache模式 首先第一步我們要來開啟cache模式。默認情況下,production環境是開啟的,但是development沒有,所以要開啟它。 進入`config/environments/development.rb`文件中,把`config.action_controller.perform_caching`設為true。 ``` config.action_controller.perform_caching = true ``` 修改完,記得重啟服務器。 ##### 2.2 使用html片斷cache 為了方便測試和了解整個原理,我們先不使用redis來存放cache數據,只使用默認的文件來存放數據。 以本站為例,我們要把首頁的"最近的文章"那部分加上html片斷的cache。 使用html片斷cache,rails提供了一個helper方法可以辦到,很簡單,只需要把需要的html用cache包起來。 ``` .row - cache do .col-md-6 .panel.panel-default .panel-heading div 最近的文章 .panel-body - @articles.each do |article| p.clearfix span.pull-right = datetime article.created_at = link_to article.title, article_path(article) ``` 我們先在頁面刷新一下,然后通過日志來觀察。 先發現訪問起來比平時慢一點點,因為它在把cache存到文件中,具體的log是下面這樣的。 ``` Started GET "/" for 127.0.0.1 at 2015-10-30 16:19:27 +0800 Processing by HomeController#index as HTML Cache digest for app/views/home/index.html.slim: 8e89c7a7d1da1d9719fca4639859b19d Read 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" = $1 ORDER BY id DESC LIMIT 10 [["published", "t"]] Group Load (3.5ms) SELECT "groups".* FROM "groups" WHERE "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" = $1 ORDER BY visit_count DESC LIMIT 10 [["published", "t"]] Group Load (2.3ms) SELECT "groups".* FROM "groups" WHERE "groups"."id" IN (1, 3, 4) Group Load (4.4ms) SELECT "groups".* FROM "groups" Write fragment views/localhost:4000//8e89c7a7d1da1d9719fca4639859b19d (41.7ms) ... ``` 主要就是`Cache digest`、`Read fragment`和`Write fragment`部分。 `Cache digest`是產生一個md5碼,這個碼來標識html的片斷,會很有用,我們等下再來細說。 `Read fragment`是讀取html片斷(以文件形式存儲),根據之前產生的md5標識,發現不存在,就會生成一個html片斷并存起來,就是`Write fragment`。 默認情況下,產生的html片斷文件是存在/tmp/cache目錄里的,如下: ``` ~/codes/rails365 (master) $ tree tmp/cache/ tmp/cache/ ├── 20B │ └── 6F1 │ └── views%2Flocalhost%3A4000%2F%2F8e89c7a7d1da1d9719fca4639859b19d ``` 打開`views%2Flocalhost%3A4000%2F%2F8e89c7a7d1da1d9719fca4639859b19d`這個文件,就會發現里面存儲的就是html的片斷。 現在我們在刷新一遍頁面,再來看看日志。 ``` Started GET "/" for 127.0.0.1 at 2015-10-30 16:53:18 +0800 Processing by HomeController#index as HTML Cache digest for app/views/home/index.html.slim: 8e89c7a7d1da1d9719fca4639859b19d Read fragment views/localhost:4000//8e89c7a7d1da1d9719fca4639859b19d (0.3ms) ... ``` 就會發現`Write fragment`沒有了,也不查詢數據庫了,數據都從html片斷cache取了。 這樣還不算完成。我們要考慮一個問題,就是我們改了數據或html的內容的時候,cache會自動更新嗎? ##### 2.3 Cache digest 先來說更改html片斷代碼本身的情況。 我們把"最近的文章"改成”最新的文章",然后我們來觀察是否會生效。 最終通過查看日志,發現還是產生了`Write fragment`,說明是生效的。 這個原理是什么呢? 我們找到cache這個helper方法的[源碼](https://github.com/rails/rails/blob/master/actionview/lib/action_view/helpers/cache_helper.rb)。 ``` def cache(name = {}, options = {}, &block) if controller.respond_to?(:perform_caching) && controller.perform_caching safe_concat(fragment_for(cache_fragment_name(name, options), options, &block)) else yield end nil end ``` 發現關鍵在`cache_fragment_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 def fragment_name_with_digest(name, virtual_path) #:nodoc: virtual_path ||= @virtual_path if virtual_path name = controller.url_for(name).split("://").last if name.is_a?(Hash) digest = Digestor.digest name: virtual_path, finder: lookup_context, dependencies: view_cache_dependencies [ name, digest ] else name end end ``` 關鍵就在`fragment_name_with_digest`這個方法里,它會找到cache的第一個參數,然后用這個參數的內容生成md5碼,我們剛才改變了html的內容,也就是參數改變了,md5自然就變了,md5一變就得重新生成html片斷。 所以cache方法的第一個參數是關鍵,它的內容是判斷重不重新產生html片斷的依據。 改變html片斷代碼之后,是會重新生成html片斷的,但如果是在articles中增加一條記錄呢?通過嘗試發現不會重新生成html片斷的。 那我把@artilces作為第一個參數傳給cache方法。 ``` .row - cache @articles do .col-md-6 .panel.panel-default .panel-heading div 最近的文章 .panel-body - @articles.each do |article| p.clearfix span.pull-right = datetime article.created_at = link_to article.title, article_path(article) ``` 發現生成了`Write fragment`,說明是可以的,頁面也會生效。 ``` Cache digest for app/views/home/index.html.slim: 1c628fa3d96abde48627f8a6ef319c1c Read 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" = $1 ORDER BY visit_count DESC LIMIT 10 [["published", "t"]] ``` 但是,除此之外,還有sql語句生成,而且以后的每次請求都有,即使命中了cache,因為@articles作為第一個參數,它的內容是要通過數據庫來查找的。 那有一個解決方案是這樣的:把@articles的內容也放到cache中,這樣就不用每次都查找數據庫了,而一旦有update或create數據的時候,就讓@articles過期或者重新生成。 為了方便測試,我們先把cache的存儲方式改為用redis來存儲數據。 添加下面兩行到Gemfile文件,執行`bundle`。 ``` gem 'redis-namespace' gem 'redis-rails' ``` 在`config/application.rb`中添加下面這一行。 ``` config.cache_store = :redis_store, {host: '127.0.0.1', port: 6379, namespace: "rails365"} ``` `@articles`的內容要改為從redis獲得,主要是讀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 end end ``` 創建或生成一條article記錄,都要讓redis的數據無效。 ``` class Admin::ArticlesController < Admin::BaseController ... def create @article = Article.new(article_params) Rails.cache.delete "articles" ... end end ``` 這樣再刷新兩次以上,就會發現不再查數據庫了,除非添加或修改了文章(article)。 完結
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看