Commit Graph

42 Commits

Author SHA1 Message Date
michael-grunder
55dd05356d Merge remote-tracking branch 'kotas/opt-read-timeout'
Conflicts:
	library.c
2013-02-11 12:42:49 -08:00
michael-grunder
6529458c0e Add include for smart_str 2013-01-19 13:34:26 -08:00
kotas
3764a6cd80 add Redis::OPT_READ_TIMEOUT option for issue #70 2012-10-04 22:18:18 +09:00
Nicolas Favre-Felix
2e70c5a5a9 Merge branch 'reconnect-select' of https://github.com/0/phpredis into 0-reconnect-select 2012-05-27 22:24:58 +01:00
michael-grunder
f00ed2aad8 Unit tests for EVAL, EVALSHA, DUMP, RESTORE, _unserialize, and _prefix 2012-05-19 13:47:17 -07:00
michael-grunder
048e4b2de8 getLastError method 2012-05-11 17:58:54 -07:00
michael-grunder
9c9c63fb46 Initial commit of EVAL and EVALSHA 2012-05-09 17:48:11 -07:00
Dmitri Iouchtchenko
db3c3c5d2a Added SELECT after reconnect
This prevents the DB number from being reset to zero after a timeout and
subsequent automatic reconnect.
2012-05-08 22:50:36 -04:00
Eric Hohenstein
39df0b7a2c fixing issue with re-connect logic
There was an issue with the re-connect logic such that it would sometimes only partially apply a transaction. The redis_check_eof() function in library.c was automatically and invisibly re-connecting to the redis server when php_stream_eof() returned non-zero. If this happened to happen after a transaction had been partially stored, the server was rolling back the transaction but the phpredis library was continuing as if it was still applying the transaction so the remaining commands were being applied immediately. The result was that the portion of the transaction after the re-connect was applied (although not atomically) but the portion before the reconnect was thrown away by the server.

This change causes the phpredis library to fail (by throwing a RedisException) instead of reconnecting if the client session is in multi mode or it is watching any keys. Either of these conditions indicate that the server has lost the state of the session and the client needs to rebuild it. Because transactions can fail due to watched keys having been changed, clients that use transactions should already be coded to handle transaction failures using retry logic. With this change, clients that use transactions when talking to redis servers that use connection timeout, they will have to add a try...catch within the transaction retry loop to handle this type of failure. Clients that do not use transactions and clients that use transactions with redis servers that do not use connection timeout will be unaffected.

Perhaps not coincidentally, this change also fixes a well known but previously not well understood bug that causes RedisExceptions to be thrown with a message like  "protocol error, got '*' as reply type byte". My company began integrating redis into our service that handles 500,000 daily active users in April of this year. Prior to this fix, when we had our redis server connection timeout set to 5 seconds we would get hundreds of those error messages showing up in our php error logs per day. This wasn't a huge problem but it was concerning enough to raise the connection timeout to 30 seconds which reduced the rate of the errors but didn't eliminate them. At one point we had a process that was failing repeatedly with this error with a 30 second timeout so we had to raise the timeout all the way up to 300 seconds. A long timeout is not idea for a high throughput website like ours since it can cause failures to cascade from one system to another due to resource limits and requests holding on to connections for a long time. After introducing this fix roughly a month ago we have not had a single instance of RedisException show up in our php error logs (except for legitimate errors related to the server being down) even after lowering the server timeout back down to 5 seconds.

To reproduce the problem without this fix, set the redis server timeout configuration to 3 seconds and use the following test php script:

<?php

define('MAX_FAILURES', 1);

function get_redis() {
    $r = new Redis();
    $r->connect('localhost');
    return $r;
}

$r = get_redis();

$r->set('foo', '123');
$r->set('bar', 'abc');

if (isset($_GET['trans']) && $_GET['trans']) {
    $completed = false;
    $failures = 0;
    while (!$completed && ($failures < MAX_FAILURES)) {
        try {
            $trans = $r->multi();
            $trans->set('foo', $_GET['foo']);
            if (isset($_GET['sleep']) && $_GET['sleep']) {
                sleep($_GET['sleep']);
            }
            $trans->set('bar', $_GET['bar']);
            var_export($trans->exec());
            echo '<br/>';
            $completed = true;
        } catch (RedisException $e) {
            echo 'transaction failed<br/>';
            $failures++;
            $r = get_redis();
        }
    }
} else {
    $r->set('foo', $_GET['foo']);
    if (isset($_GET['sleep']) && $_GET['sleep']) {
        sleep($_GET['sleep']);
    }
    $r->set('bar', $_GET['bar']);
}

echo $r->get('foo');
echo '<br/>';
echo $r->get('bar');

?>

****************************
*** Results without this fix
****************************

foo=bar&bar=baz&trans=0&sleep=0
bar
baz

foo=bar&bar=baz&trans=1&sleep=0
array ( 0 => true, 1 => true, )
bar
baz

foo=bar&bar=baz&trans=0&sleep=30
bar
baz

foo=bar&bar=baz&trans=1&sleep=30
NULL
123
baz

Notice in this last example the call to exec() did not return anything and the value of the key 'bar' was modified by the transaction but the value of the key 'foo' was not even though the calls to set() on both keys were made between a call to multi() and a call to exec().

*************************
*** Results with this fix
*************************

foo=bar&bar=baz&trans=0&sleep=0
bar
baz

foo=bar&bar=baz&trans=1&sleep=0
array ( 0 => true, 1 => true, )
bar
baz

foo=bar&bar=baz&trans=0&sleep=30
bar
baz

foo=bar&bar=baz&trans=1&sleep=30
transaction failed
123
abc

Notice in the last example where the transaction failed message is printed, it is necessary to explicitly reconnect to the redis server. Trying to reuse the same redis object after it has failed to reconnect will result in a segmentation fault. I believe this was an existing problem with the phpredis library and it is not addressed by this change.
2011-12-22 12:26:36 -08:00
Charles
c9a6ce2cf4 Build fix for win32 (phpredis 2.1.3) 2011-06-30 21:17:23 +07:00
Zakay Danial
c561e89ff1 Added support for user specified persistent connection id 2011-02-04 09:45:57 +01:00
Nicolas Favre-Felix
2e7e610640 Added key prefix. 2010-12-28 14:12:59 +01:00
Nicolas Favre-Felix
b1142fe27e Merge branch 'master' into serializer
Conflicts:
	library.c
2010-12-28 12:04:36 +01:00
Simon Effenberg
54e5e5f4e7 added missing threaded parameters 2010-12-15 16:32:05 +01:00
Nicolas Favre-Felix
7c2478629d Merge branch 'master' into serializer 2010-12-15 16:10:31 +01:00
Simon Effenberg
ab9a88ed4f added pconnect, has to be tested and checked 2010-12-15 09:44:35 +01:00
Nicolas Favre-Felix
14fbb6b917 Merge branch 'master' into serializer 2010-12-13 10:37:01 +01:00
Nicolas Favre-Felix
5a4eb10695 Fixed a large number of warnings when compiled with -Wall (thanks to github user lstrojny for the initial work on this). 2010-12-13 10:18:42 +01:00
Nicolas Favre-Felix
b2afc58654 First work on serializer. 2010-12-08 23:47:25 +01:00
Nicolas Favre-Felix
44f048c523 Added support for UNIX Domain Sockets. 2010-12-07 23:10:29 +01:00
LeonLegion
0559f55863 Types REDIS_ZSET and REDIS_HASH added. 2010-11-24 02:15:10 +03:00
Nasreddine Bouafif
196637e95c bugfix for the issue 50 : throwing exception for protocol errors. 2010-10-13 14:31:52 +02:00
Nicolas Favre-Felix
cab7f8e3c8 Fixes for static compilation. 2010-10-12 14:23:02 +02:00
Nicolas Favre-Felix
25eb12fb2c Added floating-point timeout for better precision. 2010-10-06 14:37:42 +02:00
Nicolas Favre-Felix
c67e2ddf74 Re-added HMGET + doc & unit tests. 2010-09-20 17:33:59 +02:00
Nicolas Favre-Felix
f031b3c628 Cleanup. 2010-09-19 16:15:10 +02:00
Nicolas Favre-Felix
b12a48bd5b Very large refactoring, simplified a lot of code. 2010-09-17 15:33:45 +02:00
Nicolas Favre-Felix
b5c9d0cdec More improvements on MULTI/EXEC. 2010-09-17 14:31:09 +02:00
Nicolas Favre-Felix
c697ca1df3 Simplified code for pipeline and multi/exec. 2010-09-17 14:22:08 +02:00
Nicolas Favre-Felix
6edae7c4b0 Fixed ZTS problems. 2010-08-17 14:24:09 +02:00
Nicolas Favre-Felix
04976d36f3 Small fixes. 2010-08-17 11:44:13 +02:00
Nicolas Favre-Felix
0a9f7d8866 Removed global variables. 2010-08-17 11:11:18 +02:00
Nicolas Favre-Felix
576dd065e0 More MULTI/EXEC/PIPELINE fixes. 2010-05-13 17:58:49 +02:00
Nicolas Favre-Felix
b9aaaa74f2 Working better, cleaned a lot of leaks. 2010-05-12 19:03:43 +02:00
Nicolas Favre-Felix
f6de217ea0 MULTI/EXEC and pipeline working for the first time. 2010-05-12 17:07:03 +02:00
Nicolas Favre-Felix
fbfe6f48fd Fixed more MULTI/EXEC code. 2010-04-22 14:29:40 +02:00
Nicolas Favre-Felix
31c42af8f1 Crash fix. 2010-04-22 13:34:58 +02:00
Nicolas Favre-Felix
9ddf5fc6a9 Big cleanup. 2010-04-22 12:26:04 +02:00
Nasreddine Bouafif
e7c67ccf42 refactoring commands 2010-04-22 11:01:18 +02:00
Nasreddine Bouafif
7e6d762ea0 Pipeline : refactoring using macro (need to validate/refactor all the commands) 2010-04-08 18:37:51 +02:00
Nasreddine Bouafif
f17006de69 Pipeline process implementation : need to impact the modifications on the rest of functions and clean some memory leaks. 2010-04-07 16:39:42 +02:00
Nasreddine Bouafif
f4af354475 re-organize code, init pipeline 2010-04-01 18:58:02 +02:00