Redify

State of Code
Redify is currently under development and is not ready for public usage yet.
Introduction
Redify intends to act as a plug-and-play Redis layer for your ActiveRecord models. By adding the following to your models...
class Foo < ActiveRecord::Base
redify
end
... a few common database operations will be done through Redis instead of ActiveRecord, increasing overall speed of queries and decreasing your database server access frequency.
Considerations
Redify will increase your server memory usage, depending on data size that is stored into Redis. It will also likely increase the boot time of your application, since Redify loads all data into Redis upon model initialization. Please keep those in mind when using this gem.
Requirements
Instead of directly connecting into Redis itself, Redify requires an already connected handler that responds to Redis commands (like get
, hmget
, etc), so it is not restricted to a specific Redis client.
It works best with models which primary keys are either numeric or strings without any special characters, since they are used to compose key names in Redis.
Redify requires ActiveSupport ~> 3.0.
Installation
Add this line to your application's Gemfile:
gem 'redify', :git => 'git://github.com/pauloddr/redify.git'
And then execute:
$ bundle
Or install it yourself as:
$ gem install redify
Setting Up
You can set up default options in Redify::Settings
in your initializer scripts. The following example assumes you have defined a $redis
variable elsewhere in your application pointing to a handler that responds to Redis commands:
Redify::Settings.default_handler = $redis
You can define a namespace to be prepended to every key handled by Redify. By default, this namespace equals to "Redify"
unless you set this option. A couple examples for Rails applications:
Redify::Settings.namespace = "#{Rails.application.name}:#{Rails.env}"
Redify::Settings.namespace = "#{Rails.application.name}:#{Rails.configuration.assets.version}"
Redis Structure
Considering a model called User
and an empty namespace, Redify will automatically generate the following keys in Redis when you "redify" a model:
Users
- a hash with extended data about the model with the following fields:
field_names
- a string with a comma-separated, ordered list of field names.field_types
- a string with a comma-separated, ordered list of field types. Possible values are: string
, number
, float
, date
, datetime
and boolean
.associations
- a string with a comma-separated list of associations that are "redified' for the model.redify_status
- internal status of model "redification". Possible values are "LOADING"
and "READY"
.
Users:All
- an ordered list of primary keys from Users.User:N
(for each record) - an hash containing information about a single record, where N
is the record primary key.
When you throw in an associated model called Post
, where user has_many posts
, you also get:
Posts
Posts:All
Post:N
(for each record)User:N:Posts
(for each User
) - an ordered list of Post IDs that belong to User#N
.
Operations
Redify will use Redis for the following common operations:
User.all
User.find N
User.first(n)
and User.last(n)
User#Posts
(associations)
Redify will fall back to ActiveRecord on more complex queries until it works with more finders and options.
Initialization Options
Upon "redification" of a model, you can pass some extended options.
:with_associations => [...]
class User < ActiveRecord::Base
has_many :posts
redify :with_associations => [:posts]
end
You can also pass :all
instead of an array of associations to always redify all associations.
:through => <redis_handler>
Redify will use the default Redis handler passed to Redify::Settings.default_handler
unless you specify this option. Namespace rules still apply to all Redis instances in use.
Finder Options
:skip_redify => true
Example:
User.all :skip_redify => true
Use this option if for some reason you want to go straight to ActiveRecord.
:as => :hash
Example:
User.all :as => :hash
Redify will return raw hashes instead of ActiveRecord models. This will yield the fastest speeds. Use this if you can affort not relying on ActiveRecord instances.
If the model has any redified associations, they will be available as an array of IDs. For example, when an user has many posts and they're included in the query (as in, :include => :posts
), its hash will return as:
{id: 1, name: "...", ..., post_ids: [1, 2, 3,...]}
Scalability and Maintenance
Redify is intended to work with multiple servers running multiple spawns of the same application, all sharing the same Redis connection. Data integrity is kept tight through a solid namespace composition and some under-the-hood work (keep reading) within the gem. That way, Redis can work as a large pool of data serving multiple applications in the same or different servers.
To make sure multiple instances don't interfere with each other, Redify sets a root-level namespace in Redis called RedifyApps
, followed by the server hostname, and finally the application namespace. This structure is then used to keep track of all processes running Redify applications. It maintains itself on demand by running a sanity check upon application boot, deleting old keys from applications that are no longer being used by any active processes.
Wishlist (TODO)
In no particular order...
- make it work with more finders
- implement a simple index system with tags (a.k.a. "poor man's elastic search")
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request