Problem/Motivation

The order of multiple keys from \Memcache::get() when called with an array isn't guaranteed to match the requested key order. This can be difficult to reproduce locally, but I have reproduced in an environment with multiple webheads (each running their own memcache that are then chained together).

This issue produces things like random ordering of nodes on the node/add route, and may have even more, yet to be discovered, serious consequences.

Proposed resolution

For \Memcached::getMulti() use Memcached::GET_PRESERVE_ORDER .

For DrupalMemcache::getMulti(), add an array merge with the original keys to ensure order is preserved.

Remaining tasks

User interface changes

API changes

Data model changes

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

jhedstrom created an issue. See original summary.

jhedstrom’s picture

Assigned: jhedstrom » Unassigned
Status: Active » Needs review
FileSize
1.01 KB

And the patch.

damiankloip’s picture

This makes sense, I am all for consistency :) Just a couple of things:

+++ b/src/DrupalMemcache.php
@@ -103,6 +103,10 @@ class DrupalMemcache extends DrupalMemcacheBase {
+    $keys = array_intersect_key(array_flip($keys), $cid_results);
+    $cid_results = array_merge($keys, $cid_results);

Instead of doing this why don't we just iterate over the cid lookup array and create the $cid_results return array from that order? We have to iterate anyway..

+++ b/src/DrupalMemcached.php
@@ -71,7 +71,8 @@ class DrupalMemcached extends DrupalMemcacheBase {
+    $null = NULL;

This is not really a NULL, maybe we just call this $cas or something?

jhedstrom’s picture

FileSize
590 bytes
2.3 KB

This addresses the latter part of #3. I started to look at iterating, but we aren't already iterating over the full keys, so I'm not sure if that approach would be any better than the array_merge approach.

damiankloip’s picture

Status: Needs review » Needs work

jhedstrom, this looks like it also contains the original patch from #2467005: bin gets ignored in cache key unless each bin is declared in settings. Fancy removing that, then we can get this in.

damiankloip’s picture

+++ b/src/DrupalMemcache.php
@@ -103,6 +103,10 @@ class DrupalMemcache extends DrupalMemcacheBase {
+    // Order isn't guaranteed, so ensure the return order matches that requested.

1 char over the limit :)

jhedstrom’s picture

Status: Needs work » Needs review
FileSize
1.03 KB

Oops. Here's the patch from #4 without the other fix in it. Also addressed #6.

damiankloip’s picture

That looks good, but I just had a thought. By this point, the $cid_results has the $cids that were passed into the call rather than the memcache keys. It's quite possible that a cid could just be a numeric value, like an entity ID? If so, array_merge would append instead of replace the values?

We don't have this in core itself, but a custom cache table could easily do that.

dawehner’s picture

Can't we leverage array_intersect_key or so to sort the result by the CIDs?

damiankloip’s picture

FileSize
1.11 KB

Like this instead maybe.

EDIT: Doh, forgot the comment from your previous patch!

damiankloip’s picture

@dawehner sorry missed your comment there! That is basically what this patch does now. We were thinking the same I guess.

  • damiankloip committed ed786f3 on 8.x-2.x
    Issue #2562833 by jhedstrom, damiankloip: Order isn't guaranteed in \...
damiankloip’s picture

Status: Needs review » Fixed

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.