Lumière sur Memcached

memcached-banniere

Pour votre boutique Magento il est commun d'utiliser une base de données Memcached ou Redis. Elle va gérer le cache et/ou les sessions. Le plus souvent utilisées dans des architectures multi-serveurs, ces bases de données améliorent les performances. Elles facilitent également la scalabilité horizontale de votre applicatif.

Néanmoins, mal configurés, ces outils peuvent parfois avoir des effets inattendus sur votre applicatif.

Ayant récemment rencontré un dysfonctionnement de sessions utilisateurs pour l'une de nos boutiques Magento, j'exposerai, à travers cet article, un premier éclaircissement sur le fonctionnement interne de Memcached.

Memcached

Mais avant tout, qu'est-ce que Memcached ? Memcached est une base de données clé-valeur à stockage en mémoire. L'ensemble des données est stocké en mémoire. Ces données sont accessibles via des clés uniques.

Memcached a un système d’allocation mémoire particulier. Il n’utilise pas de simples "malloc()/free()" pour travailler, mais un système appelé "slabs allocator".

Organisation et démarrage

Dans Memcached, les données sont stockées dans des 'slab classes’. Chaque slab class contient des ‘pages'. Chaque page est remplie par des 'chunks’.

Au démarrage, une ‘page' est créée automatiquement pour chaque ‘slab’ et divisée en plusieurs ‘chunks’.

Slab

Un ‘slab’ est donc une collection de ‘pages’, divisée en ‘chunks’ de la même taille. Chaque ‘slab’ est référencé par la taille de ses ‘chunks’. ( Slab class 80KB, Slab class 100KB etc…).

Lorsque l’on stocke un objet, la taille de cet objet est déterminée puis comparée à la taille des ‘slab classes’ pour y être rangé. Ainsi, un objet avec une taille plus grande que 80KB mais moins que 100KB sera stocké dans la 'Slab class 100KB’.

Page

Un ‘slab class’ peut avoir une ou plusieurs pages. Par défaut, la taille maximale d’une page est de 1MB (configuration). Donc, selon la taille d’un ‘chunk’ d’une ‘slab class’, une page pourra contenir un certain nombre de ‘chunk’. Il y a potentiellement une perte place.

Exemple

Supposons les paramètres de configuration suivants :

‘min chunk size’ : 100KB (-n 102400)
‘growth factor’ : 3 (-f 3)
‘maximum page size’ : 1MB (-I 1M)
‘maximum memory’ : 3MB (-m 3)

Lorsque Memcached va démarrer, celui-ci va créer 3 ‘slab classes’. Je vais les nommer A, B et C avec chacun une ‘page’ de base. Ces ‘slab classes’ sont prêts à recevoir des objets, dans sa division en ‘chunks’.

Slab class A(100KB) : 
    Page1 - Peut contenir 10 objets ayant une taille 
        => 100KB (1MB / 100KB), aucune perte.
Slab class B(300KB) : 
    Page1 - Peut contenir 3 objets ayant une taille 
        => 300KB (1MB / 300KB) dont 100KB de "gâché".
Slab class C(900KB) : 
    Page1 - Peut contenir 1 objet ayant une taille 
        => 900KB et 100KB "gâché".

Mémoire total occupé : 3MB.
Mémoire total utilisé : 2.8MB.

Chaque fois qu’une page est pleine, une nouvelle page est créée pour le ‘slab class’. Chaque ‘chunk’ est utilisé, mais pas forcément plein.
Dans mon exemple schématique, chaque ‘slab classes’ ne peut contenir qu'une page.

Évictions

Prenons le scénario d’enregistrement suivant :

11 objets de 80KB

Les dix premiers vont être enregistrés dans la ‘slab class A(100KB)'. Arrivé au onzième, la ‘Page1’ du ‘slab class A(100KB)’ est pleine. Il est impossible de créer une nouvelle page.

En raison de sa taille, l'objet ne peut pas être stocké dans la ‘slab class B(300KB)’. Memcached va le faire dans cette même ‘slab class A(100KB)’. Il va devoir procéder à un petit ménage pour arriver à ses fins.

Memcached va alors appliquer la règle LRU (Least Recently Used). Il va enlever l’objet N°1 du ‘slab class A(100KB)’ pour libérer un slot de 100KB. Le onzième objet peut alors être stocké dans le ‘slab class A(100KB)’.

Ce mécanisme s'appelle l’Éviction.

Cas pratique Magento

Comme indiqué en préambule, nous avons rencontré un dysfonctionnement pour les sessions utilisateurs.

La très efficace interface phpMemcachedAdmin, nous a permis de remarquer que la division par défaut en ‘slab class’ n'était pas adaptée à la taille de nos sessions. La moitié d'entre elles étaient inutilisées, bien qu'une page leur avait été réservée.
Celles-ci étaient principalement stockées dans les dernières ‘slab class’ allouées par Memcached. Ces ‘slab class’ ne disposaient pas d'assez de ‘chunks’ pour satisfaire notre utilisation.

Pour corriger la situation, nous avons redéfini le paramètre ‘min chunk size’ (-n). Désormais, Memcached commence sa répartition à un niveau plus proche de la taille moyenne de nos sessions.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.