Redis, Part 1:
Intro, Setup, and
Basic Commands
This is the first in a series of posts about Redis, a key-value database and open source project created by Salvatore Sanfilippo. Most web applications are built on a relational database, and the key-value database (if used at all) is a volatile cache. My goal is to show that Redis is a suitable replacement for a relational database and an exciting and powerful new technology on which to build web applications.
I’ll start with setup and basic commands; continue with lists, sets, and some fancier stuff like key expiration; and finish with a simple Ruby application that will demonstrate the covered topics.
Redis is the coolest bit of software I’ve seen in ages and I hope this series helps to spread the word and get more people to try it.
What Is Redis?
Redis is a key-value database. Unlike a relational database, which is comprised of tables containing columns of data definitions and rows of data, a key-value database stores values, each of which is referenced by a unique key. To get a value out of the database, we send the corresponding key. It’s a little like the hash, associative array, or dictionary data type in your favorite programming language.
Redis has several features that make it unique among key-value database projects:
- It stores strings, yes, but also lists and sets, so it’s flexible.
- It loads the entire dataset into RAM, so it’s fast.
- It writes the database to disk, so it’s persistent.
- It supports master-slave replication, so it’s scalable.
- It’s easy to run, so you aren’t endlessly futzing with mammoth config files
- Maybe most important, it’s easy to use, so you spend less time working with the database and more time writing your application.
I’ll cover each of these topics in greater depth as we go. Right now, let’s install it and start playing.
Setup
Redis is cake to build1. Observe:
% curl -O http://redis.googlecode.com/files/redis-1.02.tar.gz
% tar xzf redis-1.02.tar.gz
% cd redis-1.02
% make
The redis-server
binary is in the current working directory; we can run it directly, copy to /usr/local/bin
, or whatever.
To start Redis:
% redis-server
Redis is now available on localhost at port 6379. In a real application, we would interact with Redis via a client library for our language of choice. For now, we’ll just use telnet.
Open a new shell and run:
% telnet 127.0.0.1 6379
We’re now connected to Redis; let’s send it some commands.
Basic Commands
Here’s our first command (I will prefix commands with %
but you won’t see an actual prompt):
% DBSIZE
:0
DBSIZE
returns the number of keys in the database. This is a new database with no keys, so Redis says :0
.
The database is empty, but let’s try to GET
a value:
% GET hello
$-1
GET
fetches the value at the provided key. The key hello
doesn’t exist, so Redis says $-1
, which is like nil
or null
. Let’s set a value for that key:
% SET hello 5
% world
+OK
SET
takes three parameters: the name of the key, the size of the value in bytes, and, after a newline, the value itself. Here, we SET
the key hello
to the 5
-byte value world
, and Redis says +OK
. Now if we GET
again:
% GET hello
$5
world
We receive the value we just set, but with an extra line that reads $5
. Just like with SET
, the size of the value in bytes is returned first, then a newline, then the value.
We can ask Redis if a key exists:
% EXISTS bigkahuna
:0
% EXISTS hello
:1
Here, :0
and :1
mean false and true, respectively.
Let’s delete the hello
key:
% DEL hello
:1
DEL
deletes the value stored at the key hello
. The command succeeds and Redis says :1
, the number of records deleted. We can delete multiple keys by separating them with a space.
Say we want to set the value of a key only if that key doesn’t exist. Enter SETNX
:
% SETNX bigkahuna 22
% that is a tasty burger
:1
% GET bigkahuna
$22
that's a tasty burger
% SETNX bigkahuna 4
% d'oh
:0
% GET bigkahuna
$22
that's a tasty burger
The second SETNX
fails because the key bigkahuna
, having been created by the first SETNX
, now exists.
Let’s create a few more keys: english
, englash
, and englosh
. Set the value to whatever you want, remembering to enter the number of bytes and a newline first, then the value.
Redis returns data only if we feed it a valid key–it’s impossible to search for some value and get back its key. Suppose we don’t know what keys are in the database. How do we figure it out?
The KEYS
command searches all the keys for the provided pattern. Let’s get a list of every key in the database:
% KEYS *
$33
englosh englash english bigkahuna
The pattern can include globs:
% KEYS *a*
$17
englash bigkahuna
% KEYS engl?sh
$23
englosh englash english
% KEYS engl[ia]sh
$15
englash english
Finally, we can purge all of the keys from the database:
% FLUSHDB
+OK
% DBSIZE
:0
Increment & Decrement
Redis lets us increment and decrement our values. First, let’s create a counter and set it to 1:
% SET counter 1
% 1
+OK
To increment:
% INCR counter
:2
To decrement:
% DECR counter
:1
Nothing to it, right? We can also increment and decrement by values other than one:
% INCRBY counter 5
:6
% DECRBY counter 6
:0
Why do the increment and decrement commands exist? Say we’re using Redis to track the pageviews for a web site. Every URL maps to a key whose value is a counter. When a user visits a URL, we increment the counter. Imagine two visitors, v1
and v2
, visit the same URL, /about
, at the same time. Here’s how it might play out in pseudocode, using only the GET
and SET
commands:
redis.get("/about") == 5 # 5 visits so far
v1 = redis.get("/about") # visitor 1 grabs the count
v2 = redis.get("/about") # visitor 2 grabs the count
redis.set("/about", v1 + 1) # visitor 1 sets the count + 1
redis.set("/about", v2 + 1) # visitor 2 sets the count + 1
redis.get("/about") == 6 # wha?? should be 7
The problem is clear: v2
changed the counter after v1
retrieved the value but before setting the new one. The increment and decrement commands prevent this problem because they’re atomic: reading the value and changing it occur in one motion and can’t be interrupted.
We can close both Redis and our telnet session by sending the SHUTDOWN
command:
% SHUTDOWN
Connection closed by foreign host.
And that’s it for part 1. Already, we know enough commands to build a real application, but Redis has much more to offer–next time, we’ll explore lists.
- Mac OS X users must install the Developer Tools. Windows users should get along just fine using Cygwin. Linux/UNIX users shouldn’t need my help. ↩