[ Content | View menu ]

Redis and Ruby

Mark Mzyk | June 2, 2009

At the May raleigh.rb meetup, Kevin Smith gave a talk on alternative databases, in which he covered CouchDB and Redis.

The talk convinced me that Redis would be the perfect database to underpin Get Encouraged.  Redis is a key-value pair database that is blazing fast: perfect for a small Twitter app that really only needs to store tweets.

Being rather new to the Ruby world, there are obstacles that are easy for others, but confound me, since I haven’t encountered them before.  One of these obstacles is that I don’t know the gem system very well, and there isn’t a gem for Redis that you can grab using gem install that I could find.  This meant I had to figure out how to install a Redis Ruby client library gem using code from github.  Since I figure there are others who are as baffled by this as I was, here are the steps you need to take to install Redis and the redis gem on your system, using the redis-rb library.

The first step is to download the redis-rb client library from github.  It is here:

http://github.com/ezmobius/redis-rb/tree/master

There are other Redis Ruby client libraries, but my directions pertain to redis-rb, since that is the one I used.  Why start with a Redis client library and not Redis itself?  Because the redis-rb library provides a rake task that will install Redis for you, although you can still install Redis without using the rake task if you so choose.

Once you’ve downloaded redis-rb, untar or unzip it, whatever the case may be, and cd into that directory.

Install the rspec gem, if you don’t already have it:

sudo gem install rspec

Now run the rake command to install Redis:

rake redis:install

This will install Redis to /usr/bin/.  The Redis configuration file, redis.conf will be in /etc/.  Redis can be started by running /usr/bin/redis-server.  You do not need to setup a configuration file, since Redis will just use its default one; however, there are options that are worth exploring in the conf file, so at some point open up /etc/redis.conf and take a look.

Next, redis-rb requires that you have dtach installed, if you don’t already:

rake dtach:install

This installs dtach to /usr/bin/.  You don’t have to do anything with dtach, it just needs to be present on your system so redis-rb can find it.

The final step is to make the redis-rb gem, so you can use it in your code.  It’s easy enough:

rake gem

That command will package up the redis-rb gem and put it in the folder pkg under the current directory.  If you cd into the pgk directory, you can then install the gem:

sudo gem install redis

Note: while the github repo is called redis-rb, the gem it creates is called redis.

You now have Redis installed on your system, along with the redis gem to enable your Ruby code to access Redis.  Here’s some trivial example code to help get you up and running (this example is based off of one in the redis-rb github repo, where you can find more examples):

require 'rubygems'
require 'redis'
r = Redis.new
r.delete('first_key') #clear it out, if it happens to be set
puts 'Set the key {first_key} to {hello world}'
r['first_key'] = 'hello world'
puts 'The value of {first_key} is:'
puts r['first_key']

Save this code to a file, then start Redis on your machine (/usr/bin/redis-server), run the code, and watch it do its magic.  Hope that helps you get started with Redis.  Enjoy.

Update 6/3/2009: Kevin has now posted his slides from his raleigh.rb presentation.  Find them here.

Filed in: Programming.

4 Comments

  1. Comment by runeb:

    Or do:
    gem sources -a http://gems.github.com
    gem install ezmobius-redis-rb

    September 27, 2009 @ 09:34
  2. Comment by Mark Mzyk:

    Good point, runeb. At the time, I didn’t realize that github could be set as a gem source. Thanks for pointing that out so that now everyone else knows as well. That way is much easier.

    September 30, 2009 @ 15:34
  3. Comment by Jim Dennis:

    Hmmm … to play with redis using Python on my Debian box I just typed:

    sudo aptitude install redis-doc redis-server python-redis

    … the started ipython, and played with it using:

    import redis
    r = redis.Redis()
    r.keys()
    r.set(‘foo’, ‘bar’)
    r.set(‘counter’, 0)
    r.incr(‘counter’)
    [r.rpush(‘somelist’, x) for x in range(10)]
    r.lrange(‘somelist’, 0, r.llen(‘somelist’)

    … and so on.

    Which leads me to my main point: if you think of Redis as a simple key/value store then you are missing out on its best features. The fact that it supports several types of data (strings, numbers, lists, sets, ordered sets, and hash maps) and a number of coherent/atomic operations on those (increments, pushes and pops, and blocking pops with timeouts, for example) makes Redis a versatile general purpose way for co-ordinating distributed processes.

    For example it’s almost trivial to write code to implement a multi-producer/multi-consumer work distribution model through a Redis server.

    For example the following implements a simple consumer:

    while r.get(‘mystatus’) != ‘Done':
    poll = r.blpop([‘q1′, ‘q2′, …], timeout)
    if poll is not None:
    # do periodic clean-up
    continue
    key, value = poll
    # dispatch values into handlers by key …

    This is similar to a select() driven event model, but simpler and at a much higher level (without any low level socket handling issues). (Yes, you might have to wrap this all in an exception handler to catch connection lossage but even with that it’s simpler than writing this with raw sockets and select()).

    Additionally Redis supports a simple publish/subscribe feature. While the example above would ensure that each value pushed into any queue (key storing a list) was popped off by exactly one consumer … the publish/subscribe allows a number of clients to all get notification of events. (Imagine if “mystatus” in the above example had states for “Paused” as well as “Done” and the implicit “Running”; the clients could all then subscribe to an event channel and do a blocking .listen() call to receive notification of events. This might be an absurdly simplistic use of the publish/subscribe feature but it builds easily on the previous model).

    April 26, 2011 @ 03:59
  4. Comment by Mark Mzyk:

    Thanks for the examples Jim. You’re right in that Redis can be used as much more than a simple key value store. I was only just starting to explore Redis when I wrote this blog post, although I still haven’t done as much as I would like. I appreciate the code showing the versatility of a tool like Redis. I hadn’t considered using it for producers and consumers.

    April 26, 2011 @ 21:47