Problem/Motivation

When using memcache for multiple cache bins, I get a ServiceNotFoundException for a non existant service.

The output after running drush status

KEYS getMulti:array (
  'bootstrap-last_write_timestamp_cache_bootstrap' => '-bootstrap-last_write_timestamp_cache_bootstrap',
)

KEYS getMulti:array (
  'bootstrap-system_list' => '-bootstrap-system_list',
)

KEYS getMulti:array (
  'discovery-last_write_timestamp_cache_discovery' => '-discovery-last_write_timestamp_cache_discovery',
)

KEYS getMulti:array (
  'discovery-entity_type' => '-discovery-entity_type',
)

KEYS getMulti:array (
  'entity-values:user:0' => '-entity-values%3Auser%3A0',
)

KEYS getMulti:array (
  'discovery-entity_base_field_definitions:user:de' => '-discovery-entity_base_field_definitions%3Auser%3Ade',
)

KEYS getMulti:array (
  'discovery-entity_field_storage_definitions:user:de' => '-discovery-entity_field_storage_definitions%3Auser%3Ade',
)
Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: You have requested a non-existent service "user.field_user_food_blogger". in Drupal\Component\DependencyInjection\Container->get() (line 157 of          [error]
/var/www/docroot/core/lib/Drupal/Component/DependencyInjection/Container.php) #0
/var/www/docroot/core/lib/Drupal/Core/DependencyInjection/DependencySerializationTrait.php(53): Drupal\Component\DependencyInjection\Container->get('user.field_user...')
#1 [internal function]: Drupal\Core\Entity\Entity->__wakeup()
#2 /var/www/docroot/modules/contrib/memcache/src/DrupalMemcached.php(88): Memcached->getMulti(Array, NULL, 1)
#3 /var/www/docroot/modules/contrib/memcache/src/MemcacheBackend.php(101): Drupal\memcache\DrupalMemcached->getMulti(Array)
#4 /var/www/docroot/core/lib/Drupal/Core/Cache/ChainedFastBackend.php(165): Drupal\memcache\MemcacheBackend->getMultiple(Array, false)
#5 /var/www/docroot/core/lib/Drupal/Core/Cache/ChainedFastBackend.php(103): Drupal\Core\Cache\ChainedFastBackend->getMultiple(Array, false)
#6 /var/www/docroot/core/lib/Drupal/Core/Cache/UseCacheBackendTrait.php(37): Drupal\Core\Cache\ChainedFastBackend->get('entity_field_st...')
#7 /var/www/docroot/core/lib/Drupal/Core/Entity/EntityFieldManager.php(401): Drupal\Core\Entity\EntityFieldManager->cacheGet('entity_field_st...')
#8 /var/www/docroot/core/lib/Drupal/Core/Entity/EntityManager.php(154): Drupal\Core\Entity\EntityFieldManager->getFieldStorageDefinitions('user')
#9 /var/www/docroot/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php(282): Drupal\Core\Entity\EntityManager->getFieldStorageDefinitions('user')
#10 /var/www/docroot/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php(665): Drupal\Core\Entity\Sql\SqlContentEntityStorage->getTableMapping()
#11 /var/www/docroot/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php(428): Drupal\Core\Entity\Sql\SqlContentEntityStorage->buildQuery(Array)
#12 /var/www/docroot/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php(399): Drupal\Core\Entity\Sql\SqlContentEntityStorage->getFromStorage(Array)
#13 /var/www/docroot/core/lib/Drupal/Core/Entity/EntityStorageBase.php(242): Drupal\Core\Entity\Sql\SqlContentEntityStorage->doLoadMultiple(Array)
#14 /var/www/docroot/core/lib/Drupal/Core/Entity/EntityStorageBase.php(212): Drupal\Core\Entity\EntityStorageBase->loadMultiple(Array)
#15 /var/www/docroot/core/lib/Drupal/Core/Entity/Entity.php(499): Drupal\Core\Entity\EntityStorageBase->load(0)
#16 /var/www/vendor/drush/drush/lib/Drush/User/User8.php(26): Drupal\Core\Entity\Entity::load(0)
#17 /var/www/vendor/drush/drush/lib/Drush/Boot/DrupalBoot.php(558): Drush\User\User8->load_by_uid(0)
#18 /var/www/vendor/drush/drush/includes/bootstrap.inc(354): Drush\Boot\DrupalBoot->bootstrap_drupal_login()
#19 /var/www/vendor/drush/drush/includes/bootstrap.inc(509): drush_bootstrap(6, 7)
#20 /var/www/vendor/drush/drush/includes/bootstrap.inc(456): drush_bootstrap_max()
#21 /var/www/vendor/drush/drush/lib/Drush/Boot/BaseBoot.php(59): drush_bootstrap_to_phase(-2)
#22 /var/www/vendor/drush/drush/includes/preflight.inc(66): Drush\Boot\BaseBoot->bootstrap_and_dispatch()
#23 /var/www/vendor/drush/drush/drush.php(12): drush_main()
#24 {main}.
Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: You have requested a non-existent service "user.field_user_food_blogger". in Drupal\Component\DependencyInjection\Container->get() (line 157 of /var/www/docroot/core/lib/Drupal/Component/DependencyInjection/Container.php).

Settings.local.php

$settings['memcache']['servers'] = ['localhost:11211' => 'default'];
$settings['memcache']['bins'] = ['default' => 'default'];
$settings['memcache']['key_prefix'] = '';
$settings['memcache']['stampede_protection'] = TRUE;

$settings['cache']['default'] = 'cache.backend.memcache';
$settings['cache']['bins']['cache_container'] = 'cache.backend.memcache';
$settings['cache']['bins']['cache_library'] = 'cache.backend.memcache';
$settings['cache']['bins']['cache_menu'] = 'cache.backend.memcache';
$settings['cache']['bins']['entity'] = 'cache.backend.memcache';
// APCu chainedfast backends
$settings['cache']['bins']['bootstrap'] = 'cache.backend.chainedfast';
$settings['cache']['bins']['config'] = 'cache.backend.chainedfast';
$settings['cache']['bins']['discovery'] = 'cache.backend.chainedfast';
// database cache
$settings['cache']['bins']['data'] = 'cache.backend.database';
$settings['cache']['bins']['riddle_feed'] = 'cache.backend.database';
$settings['cache']['bins']['tweets'] = 'cache.backend.database';
// Debugging
$settings['cache']['bins']['dynamic_page_cache'] = 'cache.backend.memory';
$settings['cache']['bins']['render'] = 'cache.backend.memory';

docker-compose.yml

I use a docker image to run the memcached service. Apache and MySQL are run via MAMP.

version: "2"
services:
  memcached:
    image: memcached:1.4-alpine
    ports:
      - "11211:11211"
    mem_limit: 1g
    command: memcached -m 1024m
  memcached-admin:
      image: phynias/phpmemcachedadmin
      ports:
        - "8006:80"

Analysis

The debug lines above are coming from print "\nKEYS getMulti:" . var_export($full_keys, TRUE) . "\n"; being added to \Drupal\memcache\DrupalMemcached::getMulti() so I could understand what key is causing the issue.

It seems like odd data is passed to \Drupal\Core\DependencyInjection\DependencySerializationTrait::__wakeup() by memcache. When I inspect the object in xdebug, the object does not have proper _serviceIds, but its own object put int _serviceIds: see http://share.undpaul.de/bilder/jh/memcached-service-ids-wakup.png.
When using phpmemcachedadmin I could not grab the key -discovery-entity_field_storage_definitions%3Auser%3Ade via the interface, allthough it was listed in the search when searching for -discovery-entity_field_storage_definitions. So I experimentally changed \Drupal\memcache\DrupalMemcacheBase::key to allways use hash(). With doing that, everything worked fine. So I think it has something to do with special characters or the url-encoding.

Proposed resolution

* ?

Remaining tasks

* Check if there are any issues with special characters, like : in memcached.

API changes

* ?

Data model changes

CommentFileSizeAuthor
#9 2865364-8.patch514 bytescatch
#5 2865364.patch822 bytesdamiankloip
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

derhasi created an issue. See original summary.

derhasi’s picture

Issue summary: View changes

I was wrong. When always using hash(), I still run into the issue. But at least now I can get the data from the memcache server. But I do not knwo why this data should be corrupt:

stdClasscid(entity_field_storage_definitions:user:dedatafield_user_description&Drupal\field\Entity\FieldStorageConfig*iduser.field_user_description
*field_name*entity_typeuser*typestring_long	*modulecore*settingscase_sensitive*cardinality*translatable	*locked*persist_with_no_fieldscustom_storage
*indexes
*deleted
*originalId	*status*uuid$abf0652f-3283-4168-9f68-c8ba98273698*langcodede*third_party_settings*_core*trustedData*entityTypeIdfield_storage_config*enforceIsNew*typedData*cacheContextslanguages:language_interface*cacheTags*cacheMaxAge*_serviceIds*dependenciesmodule
field_user_food_bloggeruser.field_user_food_blogger,	
boolean
-$bca08560-3ae5-40c4-88be-ba2f01a886ab !"#$%&'()	*+
field_user_linkuser.field_user_link0	
link
21$64ae065b-c882-4f08-b873-4c45c7c353f6 !"#$%&'()	*+2
field_user_rankuser.field_user_rank4	
string

max_length�is_ascii5$7057018d-439e-4d87-a350-2883dc2d4f1f !"#$%&'()	*+
user_pictureuser.user_picture:	
image
<
uri_schemepublic
default_imageuuidalt
title
widthheighttarget_typefile
display_fielddisplay_default	target_idI;$a16432df-415d-4708-ab3c-8dfce13438a8default_config_hash+6k-VBFilDLuzgSOT-77CFgHFlcd5D-kqRixtH89EShU !"#$%&'()	*+F<
createdA�7?�8�expiretagsentity_field_infoentity_typeschecksum�
END
MiSc’s picture

Do you get the same result if you only use memcache?

damiankloip’s picture

Memcache currently clones objects if the $data passed to a set() call is an object. That could be the source of your problems here?

damiankloip’s picture

Status: Active » Needs review
FileSize
822 bytes

Let me know if this fixes the issue for you, thanks!

damiankloip’s picture

Version: 8.x-2.0-alpha2 » 8.x-2.x-dev

@derhasi any news on this? It would be good to get your testing as the original bug reporter. Seems like it should be an OK change generally though.

webchick’s picture

catch’s picture

Status: Needs review » Reviewed & tested by the community

This no longer applied, so I've re-rolled it.

I removed

+++ b/src/MemcacheBackend.php
@@ -193,11 +193,13 @@ class MemcacheBackend implements CacheBackendInterface {
 

I removed this hunk because $cache->serialized is used exclusively and internally by the core database cache backend.

Removing the clone looks sensible to me, other backends don't do this (apart from the MemoryBackend which is special), so moving to RTBC since all I've done here is review and re-roll.

catch’s picture

FileSize
514 bytes
Jeremy’s picture

Assigned: Unassigned » bdragon
Fabianx’s picture

Even though we do clone in 7.x, no other 8.x cache backend clones AND the semantics of __clone are different from __serialize.

e.g. clone $obj != unserialize(serialize($obj))

it can be different in certain cases.

And if an object prevents cloning, but allows serialize it would work with DB backend + APCu backend, but not memcache backend and that is bad.

So RTBC + 1.

Fabianx’s picture

Assigned: bdragon » Unassigned
Issue tags: +Needs backport to D7

Potentially should be backported to D7 as there is really no need to clone with memcache.db.inc gone.

  • catch committed 9a910f2 on 8.x-2.x
    Issue #2865364 by damiankloip, catch, derhasi, Fabianx: Symfony\...
catch’s picture

Version: 8.x-2.x-dev » 7.x-1.x-dev
Status: Reviewed & tested by the community » Patch (to be ported)