Rails Caching Strategies

Rails Caching Strategies

Some examples of strategies to use for caching various types of Rails apps.

9b0968d25731bc92a98c3e0b77e6d2ce?s=128

Benjamin Curtis

December 05, 2012
Tweet

Transcript

  1. Rails Caching Strategies Benjamin Curtis Wednesday, December 5, 12

  2. Wednesday, December 5, 12

  3. Who am I? • Playing with Rails since 0.11 •

    Working with Rails since 2005 • Founder of RailsKits, and co-founder of Honeybadger.io Wednesday, December 5, 12
  4. The Official Word • Page, action, and fragment caching •

    Data caching • Conditional GET http://guides.rubyonrails.org/caching_with_rails.html Wednesday, December 5, 12
  5. Three Scenarios • Read-heavy site • Write-heavy site • Interactive

    app (both read and write) Wednesday, December 5, 12
  6. Lots of Reads • Conditional GET • Data caching •

    Proxy Wednesday, December 5, 12
  7. Wednesday, December 5, 12

  8. module CacheController protected def uncache_it headers['Cache-Control'] = 'max-age=0, private, must-revalidate'

    end def cache_it(max_age = 30) headers['Vary'] = 'Accept' expires_in max_age, :public => true end def etag_it(is_public = true) headers['Vary'] = 'Accept' fresh_when(:last_modified => resource.updated_at.utc, :etag => resource, :public => is_public) end end Wednesday, December 5, 12
  9. http { if_modified_since before; } server { location @app {

    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_pass http://<%= @app[:name] %>; proxy_cache <%= @app[:name] %>; proxy_cache_key "$scheme$host$request_uri"; proxy_cache_valid 5m; proxy_cache_use_stale error timeout updating invalid_header http_500 http_502 http_504; proxy_max_temp_file_size 1M; } } Wednesday, December 5, 12
  10. def walk_score Rails.cache.fetch("walkscore/#{cache_key}") do JSON.parse(open("http://api.walkscore.com/score?format=json...").read) end end Wednesday, December 5,

    12
  11. Lots of Writes • Data caching • Background jobs Wednesday,

    December 5, 12
  12. Wednesday, December 5, 12

  13. def valid_project(token) r = Redis.current project = nil unless project_id

    = r.get("pass:#{token}") deny_request(token, 'Invalid API key') and return false unless project = Project.find_by_token(token) end # Skip token and active checks for the next hour if project r.pipelined do r.set("pass:#{token}", project.id) r.expire("pass:#{token}", 3600) end end project_id || project.id end Wednesday, December 5, 12
  14. Lots of Everything • Use JS (single-page app, pjax, rjs,

    ajax) • Conditional GET Wednesday, December 5, 12