Since the day I began developing web applications I have always been a huge fan of MySQL. Maybe because SQL was drilled into us at school and varsity, or maybe because of some underlying fear of the unknown. But recently I took on a project that requires huge scalability and concurrency (I’m talking about thousands of requests a second from hundreds of threads), for this my beloved MySQL would just not hold up without making the connection pool massive. So after some hesitation I took a look at Redis.
Redis is a very advanced key-value store, or as it is commonly referred a data structure server. It’s keys can be strings, lists, sets, sorted set or hashes. As different as it is, after using it for sometime I actually think I prefer the key-value approach over SQL. Key-values are easy to understand, they make logical sense when dealing with one-to-many relationships and you can customize them to the exact way you need without hampering performance too much. Furthermore, Redis is stupidly simple to setup and even easier to integrate into Rails applications. Another thing that you get for free with Redis is a messaging system, Redis naturally lends itself to sub/pub messaging systems.
The only thing you miss directly is persistence, as with Redis the entire DB is stored in RAM, however you can set it up to persist to the disk every few minutes or hours depending how critical it is for you to keep records. In my case if we lose a minute of records it’s not overly important and won’t negatively affect business too much. Another option if persistence is critical is to combine Redis and MySQL into a single solution, where Redis handles all the high volume queries and messaging and MySQL is used to persist the critical information which isn’t accessed too often. Personally I like this model and have used it multiple times to store data which is variable in size and accessed frequently. A quick use case for this, which is often outlined, is using Redis to store a list of followers in a twitter type clone and MySQL to store the “Tweets”.
In order to integrate Redis into your Ruby app just run ‘gem install redis’ and include ‘redis’. From here on out it is essentially the same as running commands from the redis-cli. To install the redis server you can just run “brew install redis” on OSX, or “sudo apt-get install redis” on Ubuntu. From here you just boot the server using the “redis-server” command. To test the performance of Redis on your machine run “redis-benchmark”. On my 2011 Macbook Pro I can get on average about 40 000 requests/s which is more than enough for even fairly large web applications. I look forward to testing this on one of our production servers, but until then I have yet to be limited by my 40 000 requests/s.
require 'redis' redis = Redis.new # Assuming you use the default server port on localhost redis.rpush "some:db:key", "Hello" redis.rpush "some:db:key", "World" str1 = redis.lpop "some:db:key" str2 = redis.lpop "some:db:key" puts str1 + " " + str2
It is that easy to get a Redis Hello World app to run. The Ruby Redis supports most, if not all, of the standard Redis commands.
I have also used Redis as a standalone database and use the Ruby “Ohm” ORM wrapper to create Redis based Models. Ohm is simple and easy to understand, and allows you to crete complicated, yet logical Models.
In a future post I will outline how to interface Sequel and Redis into a powerful and dynamic database system, and how to use PubSub for real-time notifications across applications.
The tools I have outlined here:
Redis – http://redis.io/
Redis Gem – http://github.com/redis/redis-rb