drobtravels / readthis

Pooled active support compliant caching with redis

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Gem Version Build Status Code Climate Coverage Status

Readthis

Readthis is a drop in replacement for any ActiveSupport compliant cache. It emphasizes performance and simplicity and takes some cues from Dalli the popular Memcache client.

For new projects there isn't any reason to stick with Memcached. Redis is as fast, if not faster in many scenarios, and is far more likely to be used elsewhere in the stack. See this blog post for more details.

Footprint & Performance

See Performance

Installation

Add this line to your application's Gemfile:

gem 'readthis'
gem 'hiredis' # Highly recommended

Usage

Use it the same way as any other ActiveSupport::Cache::Store. Within a Rails environment config:

config.cache_store = :readthis_store, {
  expires_in: 2.weeks.to_i,
  namespace: 'cache',
  redis: { url: ENV.fetch('REDIS_URL'), driver: :hiredis }
}

Otherwise you can use it anywhere, without any reliance on ActiveSupport:

require 'readthis'

cache = Readthis::Cache.new(
  expires_in: 2.weeks.to_i,
  redis: { url: ENV.fetch('REDIS_URL') }
)

Instances & Databases

An isolated Redis instance that is only used for caching is ideal. Dedicated instances have numerous benefits like: more predictable performance, avoiding expires in favor of LRU, and tuning the persistence mechanism. See Optimizing Redis Usage for Caching for more details.

At the very least you'll want to use a specific database for caching. In the event the database needs to be purged you can do so with a single clear command, rather than finding all keys in a namespace and deleting them. Appending a number between 0 and 15 will specify the redis database, which defaults to 0. For example, using database 2:

REDIS_URL=redis://localhost:6379/2

Expiration

Be sure to use an integer value when setting expiration time. The default representation of ActiveSupport::Duration values won't work when setting expiration time, which will cause all keys to have -1 as the TTL. Expiration values are always cast as an integer on write.

Compression

Compression can be enabled for all actions by passing the compress flag. By default all values greater than 1024k will be compressed automatically. If there is any content has not been stored with compression, or perhaps was compressed but is beneath the compression threshold, it will be passed through as is. This means it is safe to enable or change compression with an existing cache. There will be a decoding performance penalty in this case, but it should be minor.

config.cache_store = :readthis_store, {
  compress: true,
  compression_threshold: 2.kilobytes
}

Marshalling

Readthis uses Ruby's Marshal module for dumping and loading all values by default. This isn't always the fastest option, and depending on your use case it may be desirable to use a faster but less flexible marshaller.

Use Oj for JSON marshalling, extremely fast, but supports limited types:

Readthis::Cache.new(marshal: Oj)

If all cached data can safely be represented as a string then use the pass-through marshaller:

Readthis::Cache.new(marshal: Readthis::Passthrough)

Differences From ActiveSupport::Cache

Readthis supports all of standard cache methods except for the following:

  • cleanup - Redis does this with TTL or LRU already.
  • delete_matched - You really don't want to perform key matching operations in Redis. They are linear time and only support basic globbing.

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

About

Pooled active support compliant caching with redis

License:MIT License


Languages

Language:Ruby 100.0%