Redis from PHP: Comparison of Clients and Pipelining

535 views
Skip to first unread message

Ian Chilton

unread,
Jun 2, 2011, 6:03:55 AM6/2/11
to Redis DB
Hi,

I've been doing some experiment with accessing Redis from PHP as I am
using it to do some real-time stats.

I'm using the Kohana PHP framework and running on a Rackspace Cloud
512MB development server which is running Nginx, PHP-FPM, Memcache and
Redis (with another for instance MySQL). I was originally running
Redis on it's own instance and accessing over the internal network but
when comparing performance to running it on localhost, the difference
was huge.

I started off by comparing the performance of different clients with a
set, followed by expire command wrapped in a for loop.

100000 set & expire commands:
- phpredis: 16s
- predis: 21s
- rediska: 32s

500000 set & expire commands:
- phpredis: 79s
- predis: 104s
- rediska: 175s

100000 set & expire commands with pipelining:
- phpredis: 2s
- predis: 16s
- rediska: <didn't seem to return>

500000 set & expire commands with pipelining:
- phpredis: 12s
- predis: <didn't seem to return>
- rediska: <didn't try as it didn't work above>

I like phpredis the best as it is a php module so requires no extra
code in the project, you just connect to it like you do MySQL. It also
clearly performs better (I assume because it's written in C).

Does anyone have any different experience or advice on the different
clients?

My other question was about pipelining - there doesn't seem to be much
information about how this actually works and should be used with PHP
but from my tests above, the gain is significant, particularly on
phpredis.

With using the Kohana (MVC) framework, I created a base model, which
connects to redis in the constructor and has a start() function which
runs $this->redis->pipeline(); and an end() function which runs $this-
>redis->exec();.

I then extend this model from any models where I need to use redis and
use $this->redis->set() etc to perform actions.

This seems to work great with set's, I can either just call the method
in the model to perform an action, or I can call model->begin(); call
various actions in the model; model->end() and it's way faster.

Do others do anything similar, or have a different way?

What I can't get working is pipelining for retrieval operations (eg:
gets). Is this possible?

My application has a number of set's at the top, which i'm using to
increment statistics and using the above method to pipeline them. I
then need to do some get's further down to draw some elements of the
page so looking at the above stats, it would make sense to pipeline
them too. However, as the commands are not executed until the exec()
is called, get's are obviously more tricky, if at all possible.

Does anyone do such a thing?

Thanks,

Ian


Ian Chilton
Web: http://www.ichilton.co.uk/blog
Twitter: @ichilton
LinkedIn: http://uk.linkedin.com/in/ichilton

Daniele Alessandri

unread,
Jun 2, 2011, 7:59:07 AM6/2/11
to redi...@googlegroups.com
On Thu, Jun 2, 2011 at 12:03, Ian Chilton <ian.c...@gmail.com> wrote:

Hi Ian,

> Redis (with another for instance MySQL). I was originally running
> Redis on it's own instance and accessing over the internal network but
> when comparing performance to running it on localhost, the difference
> was huge.

This is due to the effects of network round-trip times and it isn't
really something exclusively related to Redis or the client being
used.

> Does anyone have any different experience or advice on the different
> clients?

I can't say anything about Rediska since I don't know how anything
about how it works or how it's implemented.

As the author of Predis, all I can say is that if you are using Redis
on the localhost and you are more interested in raw speed and reduced
memory usage than features and extensibility, then you should just
stick with phpredis. Everything changes once you start connecting to
Redis instances over the network since the differences in speed
between the two gets more or less negligible. This is something that
comes up pretty often with Predis, so you can read more about the
comparison with phpredis here:
http://github.com/nrk/predis/blob/master/FAQ.PERFORMANCES.markdown

By the way, Predis is most likely failing when pipelining those 500000
operations because it's reaching the memory_limit set for a PHP
process.

> My other question was about pipelining - there doesn't seem to be much
> information about how this actually works and should be used with PHP
> but from my tests above, the gain is significant, particularly on
> phpredis.

Pipelining works pretty much the same for all the client libraries
implemented in any language, you can read about the concept of it here
http://redis.io/topics/pipelining. To sum it up briefly, when using
pipelining you are sending multiple commands to Redis without reading
their replies. Redis will queue up the replies for those commands so
that you can read them back later by reading the network stream thus
greatly reducing the side-effects of the network round-trip times.

> What I can't get working is pipelining for retrieval operations (eg:
> gets). Is this possible?

It's not that retrieval operations aren't working, it's just that you
are queueing them up in the pipeline which means that you won't be
able to get the results until you read the stream of replies back from
Redis. Pipelining can be applied only in certain scenarios, for
example you can't perform conditional operations while pipelining (at
least not without using a second connection).

The following example should help clarify things a bit
http://github.com/nrk/predis/blob/master/examples/PipelineContext.php

Cheers,
Daniele

--
Daniele Alessandri
http://clorophilla.net/
http://twitter.com/JoL1hAHN

Reply all
Reply to author
Forward
0 new messages