Redi

Pooled redis, add a layer of indirection between server pool and key ring

The idea comes from http://blog.zawodny.com/2011/02/26/redis-sharding-at-craigslist/


Install

gem install redi

Configure

The configuration should look like a normal redis configuration with the addition of a buckets key. This tells redi how many buckets it should hash keys to before mapping them to the configured server.

redi.yml:

development:
  - :host: 192.168.0.10
    :port: 6379
    :db: 0
    :buckets: 0 - 64
  - :host: 192.168.0.11
    :port: 6380
    :db: 0
    :buckets: 65 - 127

In the example above, it is possible to scale the 2 configured servers up to 128 servers without re-keying.


Adding a new server can be done as follows:

  • start a new server process, call it r3.
  • identify buckets to move to r3 from existing server r2.
  • setup r3 as slave to replicate from r2.
  • update configuration to point buckets to r3

production:
 - :host: 192.168.0.10 # r1
   :port: 6379
   :db: 0
   :buckets: 0 - 64
 - :host: 192.168.0.11 # r2
   :port: 6380
   :db: 0
   :buckets: 65 - 95
 - :host: 192.168.0.11 # r3
   :port: 6380
   :db: 0
   :buckets: 96 - 127
  • use bucket key prefixes to prune old keys from r2.

How you do this can vary depending on your application, but something like the pseudo code below is the idea:

96..127.times do|i| # NOTE: using redis here not redi as we want to talk to r2 explicitly
  redis.del(redis.keys("n#{i}*"))
end