This project was started because I needed an authenticating and routable proxy for Redis. The main feature is a high performance, eventable, pure Ruby, implementation of the complete Redis wire protocol using the same interface as hiredis/reader.

In the worst possible scenario of very small payloads, I was benching 30k GETs per second with pure ruby and 40k/s with hiredis/reader. With larger payloads, the performance gap narrows to zero.

Ruby Gem:

gem install ruby-redis

Server:

Runs a server that looks and feels like the C redis-server

bin/ruby-redis

Run the TCL test suite from C Redis against the Ruby server

src/redis-test

Client example:

require 'redis' EventMachine.run { redis = EventMachine.connect '127.0.0.1', 6379, Redis::Client

Subscribe and publish messages will call here

redis.on_pubsub do |message| # case message # when 'psubscribe' ... end

All commands implemented uniformly with method_missing

Returns instance of Redis::Command < EventMachine::Deferrable

Pipelining is implicit

redis.set :pi, 3.14159 redis.get('pi') do |result| p result end redis.blpop('mylist', 1).callback do |result| p result EM.stop end.errback do |e| EM.stop raise e end }

Using hiredis/reader (only affects clients):

require it before you connect

require 'hiredis/reader'

Fibers; compatible with em-synchrony:

require 'redis/synchrony' Redis.synchrony

Be sure to pipeline commands when you can

redis = EventMachine.connect '127.0.0.1', 6379, Redis::Client

synchronized requests will return result or raise exception

sync = redis.synchrony

repeat transaction until success

reply = check = nil until reply redis.watch 'mykey' x = sync.get('mykey').to_i redis.multi redis.set 'mykey', x + 1 redis.badcmd redis.get('mykey') {|result| check=result reply = sync.exec end redis.close EM.stop p reply, check # ["OK", #, "4"], "4" }

Ruby to Redis type conversions:

  String === Status reply

RuntimeError === Error reply String === Bulk reply Integer === Integer reply Array === Multi-bulk reply Hash === Multi-bulk reply to hgetall NilClass === Nil element or nil multi-bulk TrueClass === :1 FalseClass === :0