Yaychris

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.

  1. 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.

Question, comments, criticisms? I’d love to hear from you. Get in touch

You should follow me on Twitter here

Back to The Archive