We're hiring!

Fixing Resque

by Michel Martens on May 21, 2010

Since redis-rb 2.0.0 came out, a lot of Resque users realized that redis-namespace (a Resque dependency) was incompatible with the most recent Redis client. It didn’t come as a surprise: I even notified Chris Wanstrath (author of Resque and redis-namespace) about this issue when we were rolling release candidates. At that time, his proposed solution was to lock Resque to redis-rb 1.0.x. I also hinted that once Redis 2 comes out, the old client would no longer work because of a change in the protocol.

For some background, Resque is a Redis-backed Ruby library for creating background jobs, placing those jobs on multiple queues, and processing them later. It uses redis-namespace, a 187 sloc gem that adds a Redis::Namespace class which can be used to namespace Redis keys.

Yesterday, a discussion took place in #redis regarding redis-namespace compatibility with redis-rb 2.0.0. There even was a suggestion to incorporate redis-namespace into redis-rb, so all libraries could profit from that solution. Even if I opposed that move (I consider redis-namespace the wrong solution to a simple problem), the underlying issue was not with redis-namespace, but with Resque itself. None of the participants in that discussion were direct redis-namespace users: they only wanted Resque to work with redis-rb 2.0.0.

Not being a Resque user myself, I had not bothered looking at its code before. Turns out I was able to make Resque 100% compatible with redis-rb 2.0.0 by replacing redis-namespace with… nothing. It wasn’t needed at all, and the namespacing functionality is now handled by an attr_accessor called namespace.

This code lives at my without-redis-namespace branch. I sent a pull request yesterday, I hope it will be incorporated soon to the main repository.

{ 1 comment }

Redis-rb 2.0.0

by Michel Martens on May 14, 2010

After a few weeks with very stable release candidates, we have just pushed version 2.0.0. Here’s a quick rundown on what’s new with the Ruby client for Redis:

Explicit > Implicit

The previous version of the client relied on method_missing to execute commands against Redis. While this was great for quickly putting together a simple client, it proved insufficient for more advanced commands like pub/sub, blocking pop, etc. Plus, relying on this technique lead to longer and more branched methods as new features were added to Redis.

The new version explicitly defines each command as a method in the Redis class. We strongly believe that explicit beats implicit. This way it’s much easier to follow what is going on for each command. We did leave method_missing in there because it’s a nice way of being able to run simple commands that are not yet known to the client, but we’ll keep adding new commands as needed.

A nice consequence of this change is that the complexity of the code was reduced drastically. Many branches were removed in favor of separate, smaller methods (this is something that could only be done with an explicit method for each command).

New protocol

This version uses the new protocol only. It means people running a Redis version older than 1.2 will be stuck with the 1.0 branch. This multi-bulk protocol is binary safe and will be the only one available once Redis 2.0 is released, for which a release candidate is expected soon.

Faster!

One of our concerns when refactoring was the impact on performance this decoupling would bring. We agreed that a good goal would be to have the new version performing at least as fast as the old one. To our surprise –and probably because of the removal of branches, hash look-ups and by avoiding method_missing– the new version performed even better.

Before:

$ ruby -Ilib benchmarking/speed.rb
7.88 Kops

After:

$ ruby -Ilib benchmarking/speed.rb
8.79 Kops

The higher the number, the better. It means that the new version executes almost a thousand operations more per second.

Redis::Distributed

The old client shipped with DistRedis, which included a hashring algorithm and supported a small subset of operations. As it wasn’t tested or documented, we started by defining all the test cases and proceeded to implement them. Some operations are impossible in a distributed scenario, but we would cover a lot of interesting cases and it is now a very reliable tool. Check the testing suite to see the range of commands that are now possible.

Support/Bugs/Help

Jump to IRC if you need instant help. We are most of the time available at #redis-rb on Freenode. If nobody can help you there, try #redis. You can also create an issue on GitHub, or fork the project and send a patch directly.

{ 4 comments }

Ohm, now using Redis Hashes

by Michel Martens on May 10, 2010

Redis 2.0.0 is around the corner, but many of us are already using 1.3.x even in production. The new version has a lot of goodies, and of special interest for libraries that map objects to Redis is the hash data type.

By using hashes, Ohm is able to squeeze all the object attributes in a single key instead of using one key per attribute, a common pattern in key/value datastores (for some history, check the article that inspired Ohm almost one year ago: case study for a Twitter clone).

This release candidate uses Redis-rb 2.0.0.rc3, the new client that is faster, binary safe and no longer relies on method_missing for building the commands.

Upgrading your database

You will need to migrate your database if you want to use Ohm 0.1.0. It comes with a helper just for that, follow the example code to upgrade.

You will also need Redis 1.3.10 or newer, grab it from http://github.com/antirez/redis.

{ 0 comments }

180 logo180LA engaged Citrusbyte to deliver a simple Facebook tab showcasing Sony Electronic’s new iSweep Panorama digital camera technology.  While not a technically challenging project, 180LA needed a product representative of the Sony brand quality and they needed it as soon as possible.

Within a day of the request, Citrusbyte had the new frame up and running on the Official Sony Electronics Facebook page.  Take a look for yourself:

Sony iSweep Panorama Facebook Page

{ 0 comments }