Let’s imagine, what we have heavy request in our application, for example for 10k jobs.
You can just populate database with fake data:
10000 . times do
Job . create ( title: Faker :: Job . title , email: Faker :: Internet . email , description: Faker :: Lorem . paragraph ( 2 ), company: Faker :: Company . name )
end
Let’s start cache implementation, based on Redis.
gem 'redis'
gem 'redis-namespace'
gem 'redis-rails'
gem 'redis-rack-cache'
And our /config/initializers/redis.rb :
$redis = Redis :: Namespace . new ( "remoote" , redis: Redis . new )
Let’s check our jobs/index page without caching implementation.
About 5000ms - not good.
# 16ms to SQL SELECT
Started GET "/" for :: 1 at 2018 - 02 - 04 22 : 04 : 41 + 0300
Processing by JobsController #index as HTML
Job Load ( 15.9 ms ) SELECT "jobs" . * FROM "jobs"
↳ app / loaders / cache_loader . rb : 9
Rendering jobs / index . html . erb within layouts / application
Rendered jobs / index . html . erb within layouts / application ( 2529.5 ms )
Completed 200 OK in 4902 ms ( Views : 2623.8 ms | ActiveRecord : 15.9 ms )
Let’s start our cache service realization.
Just what we do here, load all Job data to json (or you can use yaml for example), and store in Redis with special key:
class CacheLoader
def self . load
jobs = $redis . get ( 'jobs' )
if jobs . nil?
jobs = Job . all . to_json
$redis . set ( 'jobs' , jobs )
$redis . expire ( 'jobs' , 10 . hours . to_i )
end
JSON . load ( jobs )
end
end
Let’s improve our controller action, and make small changes in our view, because we need to iterate via json entries.
@jobs = CacheLoader . load
Let’s check our view again:
# No SQL requests
Started GET "/" for :: 1 at 2018 - 02 - 04 22 : 03 : 53 + 0300
Processing by JobsController #index as HTML
Rendering jobs / index . html . erb within layouts / application
Rendered jobs / index . html . erb within layouts / application ( 2667.9 ms )
Completed 200 OK in 2961 ms ( Views : 2700.8 ms | ActiveRecord : 0.0 ms )
Wow! 2700 ms! Much better, but I think we can improve our loader.
Let’s use ActiveRecord pluck method and make some changes in our view.
jobs = Job . pluck ( :id , :title , :email , :company ). to_json
954 ms! Sounds great.
Instead of using Redis , you can use for example Memcached store.
But in upcoming Rails 5.2, Redis cache store will be out-of-the-box feature:
https://github.com/rails/rails/pull/31134 .
This new Redis Cache Store supports Redis::Distributed, for Memcached-like sharding across Redises. It’s fault tolerant, so will treat failures like misses, rather than kill the request with an exception. It even supports distributed MGETs for that full partial collection caching goodness.
Please enable JavaScript to view the comments powered by Disqus.