php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #77056 with memcache pool, on a session key miss, other servers not checked
Submitted: 2018-10-25 09:56 UTC Modified: -
From: aleksandar dot kuktin at infostud dot com Assigned:
Status: Open Package: Session related
PHP Version: 7.3.0RC3 OS: Ubuntu
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2018-10-25 09:56 UTC] aleksandar dot kuktin at infostud dot com
Description:
------------
Using memcache extension with failover.

Regression first discovered on upgrade from PHP-5.6 to PHP-7.0, still persists in PHP-7.3.0RC3.

When using a memcache pool for HA storage of session data, as memcache does not have replication, a workaround is used. First, PHP stores the identical session data to all members of a pool. Second, reads are iterated over all members of a pool until either one is found with session data or all members are found to not contain data - which means data doesn't exist. Thus, in the event of a failure and loss of data on a subset of nodes, they are slowly repopulated as a side-effect of normal application operation, preventing data loss in all but most extreme circumstances.

This feature fails to materialize since PHP-7.0.

It may be important to note this feature also fails to materialize if using the memcached extension; it only works if using the (very old) memcache extension.

Since PHP-7.0, reads are attempted only once, and if the first node in a pool does not contain data, this is treated as if data doesn't exist - yet it does on other nodes in the pool.

As for the specifics, we believe we have excluded the memcache extension itself. We are using Ondrej's PPA repo for PHP, and with it we are using the exact same deb package (SHA256 match) for php-memcache on both PHP-5.6 and PHP-7. Issue present on both Ubuntu-14.04 and Ubuntu-16.04 (18.04 not test as of yet).

Test script:
---------------
<?php
session_start();
if (array_key_exists("opennum", $_SESSION)) {
  $myses = $_SESSION["opennum"];
} else {
  $myses = 0;
}
$_SESSION["opennum"] = $myses + 1;
echo "success? myses = ${myses}\n";


// wget it repeatedly

Expected result:
----------------
Commands issued (>), responses sent (<) to/from memcache servers by PHP-5.6:

SERVER 0
> incr mbbh79abrh9758v87pbjj012k3.lock 1
< NOT_FOUND
> add mbbh79abrh9758v87pbjj012k3.lock 768 15 1
> 1
< STORED
> get mbbh79abrh9758v87pbjj012k3
< END
> set mbbh79abrh9758v87pbjj012k3 0 86400 12
> opennum|i:1;
< STORED
> set mbbh79abrh9758v87pbjj012k3.lock 768 15 1
> 0
< STORED

SERVER 1
> incr mbbh79abrh9758v87pbjj012k3.lock 1
< NOT_FOUND
> add mbbh79abrh9758v87pbjj012k3.lock 768 15 1
> 1
< STORED
> get mbbh79abrh9758v87pbjj012k3
< END
> set mbbh79abrh9758v87pbjj012k3 0 86400 12
> opennum|i:1;
< STORED
> set mbbh79abrh9758v87pbjj012k3.lock 768 15 1
> 0
< STORED


Actual result:
--------------
Commands issued (>), responses sent (<) to/from memcache servers by PHP-7.0, PHP-7.1, PHP-7.2 and PHP-7.3.0RC3:

SERVER 0
> incr a4126f4585d5fc35dcff6b21c6fddabb.lock 1
< NOT_FOUND
> add a4126f4585d5fc35dcff6b21c6fddabb.lock 768 15 1
> 1
< STORED
> get a4126f4585d5fc35dcff6b21c6fddabb
< END
> set a4126f4585d5fc35dcff6b21c6fddabb 0 86400 12
> opennum|i:1;
< STORED
> set a4126f4585d5fc35dcff6b21c6fddabb.lock 768 15 1
> 0
< STORED

SERVER 1
> set a4126f4585d5fc35dcff6b21c6fddabb 0 86400 12
> opennum|i:1;
< STORED
> set a4126f4585d5fc35dcff6b21c6fddabb.lock 768 15 1
> 0
< STORED


Patches

Add a Patch

Pull Requests

Add a Pull Request

 
PHP Copyright © 2001-2018 The PHP Group
All rights reserved.
Last updated: Mon Dec 10 09:01:25 2018 UTC