Don't know Redis? Think Memcache, with support for for lists, and disk-based storage. You can use Redis as a database, queue, cache server or all of those combined. Let's see how you can use this power in your PHP apps.

About those disks. Well, Redis keeps the entire dataset in memory, so it's still crazy fast: 110000 SETs/second, 81000 GETs/second. Good enough for to you?

"..and from time to time the data is saved on disk asynchronously (semi persistent mode) or alternatively every change is written into an append only file (fully persistent mode). Redis is able to rebuild the append only file in background when it gets too big."

About those lists. Yes, you can store (serialized) arrays in Memcache. But everytime you change 1 element, you'd have to invalidate & overwrite the entire array. Clearly very inefficient, yet a commonly faced problem.

About this article. It's meant to help PHP developers taking their first steps into the Redis world. From here on, there are plenty of other resources online to dig deeper.

Install Redis Server

Simple on Ubuntu / Debian:

$ aptitude install redis-server

Install PHP Library

There are many different PHP client implementations. I'd like to recommend Rediska. It's feature complete and a true pleasure to work with. This code will pull in the latest Rediska source, and copy it to /usr/share/php/ so you can include it rightaway.

$ cd /usr/src
$ [ -d Rediska ] || git clone git://github.com/Shumkov/Rediska.git
$ cd Rediska && git pull && rsync -a ./library/ /usr/share/php/

Zend Framework users may want to take a different approach

Code

Alright, we are ready to start saving some data.

Let me show you 4 common Redis datatypes to work with: Keys, Lists, Sets and Sorted Sets.

Keys

In PHP syntax, a Key could be thought of as:

<?php
$firstname = 'kevin';
?>

Ok, let's save something into Redis. First, initialize a 'firstname' Key:

<?php
require_once 'Rediska/Key.php';
$Key = new Rediska_Key('firstname');
?>

Now let's give it the value 'kevin':

<?php
$Key->setValue('kevin');
?>

It's nice to know that ->setValue() instantly saves 'kevin' to Redis memory. And you don't have to worry about every losing this name, cause Redis will automatically save to disk afterwards.

Basically that's it. You've saved something in Redis!

At a later point in time you can always retrieve that name by (initializing the 'firstname' Key if you haven't already and) doing a:

<?php
echo $Key->getValue();
?>

Lists

Lists are 'collections of unsorted elements'.

In PHP syntax, a List could be thought of as a simple array:

<?php
// Names
$list = array(
    'kevin',
    'john',
);
?>

Adding new elements to a Redis Lists happens in realtime and at constant speed. Meaning that adding an item to a 10 elements List, happens at the same speed as adding an element to the to a 10 million elements List.

So that's the upside.

The downside of this, is that looking up items by index is less fast.

So use Redis Lists every time you require to access data in the same order they are added. A message queue would make a perfect List. Also see Redis Data Types

So how do you work with Redis Lists in PHP?

<?php
// Init
require_once 'Rediska/Key/List.php';
$List = new Rediska_List('names');

// Set
$List->append('kevin');
$List[] = 'john'; // Also works

// Get (this could be done at any time, by any process,
// just initialize the List again)
foreach ($List as $name) {
    echo $name . "\n";
}
?>

Easy right? Next up: Sets

Sets

Sets are 'collections of unique unsorted elements'. You can think at this as a hash table where all the values are true. So basically, the values don't really matter in this and the keys are important.

In PHP syntax, a Set could be thought of as:

<?php
// Names
$set = array(
    'kevin' => true,
    'john' => true,
);
?>

Because Redis now adds items as keys, they will be unique and you can perform operations on Sets that you can't on Lists such as:

  • Testing if a given element already exists
  • performing the intersection
  • union
  • difference between multiple Sets
  • and so forth

Now let's see how you can work with Sets:

<?php
// Init
require_once 'Rediska/Key/Set.php';
$Set = new Rediska_Set('names');

// Set
$Set->add('kevin');
$Set[] = 'john'; // Also works
$Set->add('john'); // Still only 1 'john' in the set

// Get
foreach ($Set as $name) {
    echo $name;
}
?>

Sorted Sets

Are always ordered by their 'score'. This is also how they are stored. So any time you retrieve such a Set, it's already sorted no matter what you have added.

In PHP syntax, a Sorted Set could be thought of as:

<?php
// Names with birthyears
$zset = array(
    'john' => 1979,
    'kevin' => 1983,
);
?>

If we start adding more names & birthyears, old people will automatically be stored on top. Young at the bottom.

Using Sorted Sets in PHP is ridiculously easy:

<?php
// Init
require_once 'Rediska/Key/SortedSet.php';
$ZSet = new Rediska_Key_SortedSet('birthyears');

// Set
$ZSet['kevin'] = 1983;
$ZSet->add('john', 1979); // Also works

// Get
foreach ($ZSet as $name) {
    echo $name . " was born in ";
    echo $ZSet->getScore($name) . "\n";
}
?>

Backup

Before starting to use this in production, you want to know how you can keep your data safe.

Well, just copy the DB file to a safe place. On ubuntu the file is located in /var/lib/redis/.

cp, rsync or scp will all do the trick. Redis does active writing in a temp file so you don't have to worry about data corruption. Checkout the Redis FAQ for more info.

That's it!

Don't forget to follow Lead Developer @antirez on twitter. As of march 2010 VMware is allowing him to work fulltime on Redis, so lot's of juicy updates to get from there!

This article was based on the following documents: