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", #
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