|  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #64590 Constistent hash strategy breaks session redundancy
Submitted: 2013-04-05 10:35 UTC Modified: 2017-10-24 06:59 UTC
Avg. Score:4.0 ± 0.9
Reproduced:3 of 3 (100.0%)
Same Version:1 (33.3%)
Same OS:1 (33.3%)
From: giaco dot orlandi at gmail dot com Assigned:
Status: Open Package: memcache (PECL)
PHP Version: 5.4.13 OS: Ubuntu 12.04
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2013-04-05 10:35 UTC] giaco dot orlandi at gmail dot com
- session redundancy is implemented with 2 servers (memcache.session_redundancy=3)
- memcache.hash_strategy="consistent" 
- pecl memcache 3.0.7 and also the trunk version.

Steps to reproduce:
- open a new browser instance (or delete any previous session cookie, or use curl)
- run a simple script that starts and use the session
- roughly 25% of the times it takes about "memcache.lock_timeout" seconds to complete the request

An easy way to reproduce it is to use curl, so to start a new session from scratch every time:
curl http://my-test-project/test-script.php 

Workaround: use standard hashing strategy with session redundancy.

I did a bit of digging into the source code, even if I'm not a C developer.
If a read fails from the 1st server it should read from the 2nd.
Reading always fails when starting a new session from scratch, which is normal.
The problem seems to be that after the read on the 1st server fails it sometimes 
re-select the same server, and tries 
to read from it, but that's still locked from the previous attempt.

It seems like mmc_pool_find_next() in memcache_pool.c sometimes returns the same 
server again instead of the next one, 
if the hash strategy is consistent.
Another thing I noticed is that the list of servers in the "pool" structure is 
most of the times, but not always, in 
the same order specified in php.ini.
I wonder if that's the problem, anyway it's not the problem with standard hashing. 

Relevant php.ini configuration:
session.save_handler = "memcache"
session.save_path = "tcp://session-memcache-01:11211?persistent=1&weight=1&timeout=1&retry_interval=15, tcp://session-memcache-02:11211?

; activating memcached failover
memcache.allow_failover=0 ; 
; Defines how many servers to try when setting and getting data. It's used by mmc_pool_find_next() in memcache_pool.c 
even if allow_failover=0
; the number below needs to be N+1 if you have N number of memcached nodes.
; memcache hash stragegy, consistent is the default. Use standard for session redundancy
; session lock timeout

Test script:
header('Content-Type: text/plain; charset=utf-8');
$microtime_start = microtime(true);

if(!isset($_SESSION['count'])) {
    $_SESSION['count'] = 0;
} else {
    $_SESSION['count'] = $_SESSION['count'] + 1;
echo 'Execution time: ' . (microtime(true) - $microtime_start) . PHP_EOL . PHP_EOL;

Expected result:
    [count] => 0
Execution time: 0.00088906288146973

Actual result:
// this happens roughly 30% of the times
    [count] => 0
Execution time: 3.3002619743347


Add a Patch

Pull Requests

Add a Pull Request


AllCommentsChangesGit/SVN commitsRelated reports
 [2013-04-08 02:17 UTC]
-Status: Open +Status: Assigned -Assigned To: +Assigned To: hradtke
 [2013-04-08 02:19 UTC]
Great bug report!

I will take a look and see if I can get a fix in.
 [2017-10-24 06:59 UTC]
-Status: Assigned +Status: Open -Assigned To: hradtke +Assigned To:
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Tue Jan 26 23:01:24 2021 UTC