Redis – What is Redis? And do i need it?
Redis … just another fucking noSQL database or serious competitor for memcache and all the other key/value stores out there?
What is it?
Using Redis is like using memcached but it has some cool additional features … the best one:
It’s filesystem-backed if you wish! So Redis is not just good for a caching layer … it’s a database. There are two methods of persistence: RDB is snapshoting from time to time … or AOF a append-only journal file thats written in a background task. And you can combine both methods.
Redis has an easy-to-use replication-mode (like memcached) and some cool datatypes which i will describe below.
Install and Setup
Installing is not so hard, out there are many good tutorials. You can install via apt and dotdeb-repository or just download the tar-file and run a make command. See the following links:
- http://redis.io/topics/quickstart
- http://vvv.tobiassjosten.net/linux/installing-redis-on-ubuntu-with-apt
- http://library.linode.com/databases/redis/debian-5-lenny
How to use it with PHP?
I want to use it with PHP and there are some client-classes for it and many other programming languages, check the Redis clients-page. Here is one example for Predis and below you see how you use it with PHPRedis.
“Hello World” for Predis:
require __DIR__.'/lib/Predis/Autoloader.php'; PredisAutoloader::register(); $config = array( 'host' => '127.0.0.1', 'port' => 6379, 'database' => 15 ); $client = new PredisClient($config); $client->set('hello', 'world'); $retval = $client->get('hello'); var_dump($retval); |
“Hello World” for PHPRedis:
$redis = new Redis() or die("Can'f load redis module."); $redis->connect('127.0.0.1'); $redis->set('hello', 'world'); $retval = $redis->get('hello'); var_dump($retval); |
PHPRedis seems to be much faster (it’s a PHP-extension in C) … see Benchmarks below. Install-tutorial for PHPRedis.
Playing around with datatypes…
Redis can not only store string values, you can have lists, hashmaps and sets in your database.
Lists of strings are sorted by insertion order, it’s possible to push items to the front (lpush) or the tail (rpush) of a list. A list can have 4 billion elements. Of course you can remove items form lists, get the size of a list and fetch a range of elemets by index. Inserting at a specific index is also possible.
$redis->lPush('mylist', 'item1'); $redis->rPush('mylist', 'item2'); $redis->rPush('mylist', 'item3'); $redis->lPush('mylist', 'item0'); $size = $redis->lSize('mylist'); var_dump($size); var_dump($redis->type('mylist')); var_dump($redis->lGet('mylist', 0)); var_dump($redis->lGetRange('mylist', 0, $size-1)); $redis->delete('mylist'); |
Sets can hold an unordered collection of strings. Each string can only be once in the set. You can add, remove and check set-members in a constant time regardless of the number of elements. Another datatype are sorted sets where every item has an numeric sorting-key (score).
$redis->sAdd('myset', 'item1'); $redis->sAdd('myset', 'item2'); $redis->sAdd('myset', 'item3'); var_dump($redis->sContains('myset', 'item1')); // true var_dump($redis->sContains('myset', 'item4')); // false var_dump($redis->sSize('myset')); var_dump($redis->sMembers('myset')); $redis->sAdd('myset2', 'item2'); $redis->sAdd('myset2', 'item3'); $redis->sAdd('myset2', 'item4'); var_dump($redis->sDiff('myset','myset2')); var_dump($redis->sUnion('myset','myset2')); var_dump($redis->sInter('myset','myset2')); |
Hashmaps (aka Hashes) are perfect for storing objects like “user” or “article” or whatever. It’s a key/value map stored under a distinct id. For example a user with the key user-1 can have a key/value map with {name:’derfichtl’, ‘email’:'test@test.at’} … here some examples for working with hashes:
// setting $redis->hSet('user-derfichtl', 'username', 'derfichtl'); $redis->hSet('user-derfichtl', 'email', 'derfichtl[AT]gmail.com'); $redis->hSet('user-derfichtl', 'name', 'Michael Feichtinger'); // or so: $redis->hMset('user-derfichtl', array('username'=>'derfichtl', 'email'=>'derfichtl[AT]gmail.com', 'name'=>'Michael Feichtinger')); // reading foreach($redis->hKeys('user-derfichtl') as $key) { var_dump($key.': '.$redis->hGet('user-derfichtl', $key)); } // or so: var_dump($redis->hVals('user-derfichtl')); var_dump($redis->hGetAll('user-derfichtl')); if($redis->hExists('user-derfichtl', 'name')) { var_dump($redis->hGet('user-derfichtl', 'name')); } |
A Little Performance Test
On an Amazon EC2 micro instance (Ubuntu) …
for($i=0;$i<1000;$i++) { // set // get } |
MEMCACHED: 0.10s
PREDIS (AOF onesecond): 0.20s
PHPREDIS (AOF onesecond): 0.12s
PHPREDIS (NO file-persistence): 0.09s
MYSQL: 0.155s
// set/insert for($i=0;$i<10000;$i++) { // get } |
MEMCACHED: 0.5s
PHPREDIS (AOF onesecond): 0.45s
MYSQL: 0.5s
Journal File looks like …
It’s a simple plain text file and looks so:
*2 $6 SELECT $2 15 *3 $3 SET $5 hello $5 world *3 $3 SET $5 hello $5 world
Who is using it?
Flickr, Digg, StackOverflow, GitHub, …
So, now you should know enough about Redis to talk about like a pro