2017-10-10 6 views
1

Nous utilisons la bibliothèque phpredis pour se connecter à notre cluster Redis 64 nœuds à partir de nos machines de service. Bien que nous utilisions des connexions persistantes, comme php ne réutilise pas les objets dans les requêtes, chaque requête appelle d'abord le cluster Redis puis effectue une extraction de données. Cela s'avère très coûteux car cela augmente le processeur sur l'API et Redis et augmente également l'utilisation du réseau pour les méta-informations (CLUSTER SLOTS) qui pourraient autrement être mises en cache. Fondamentalement, nous voulons que l'objet de connexion de cluster Redis soit réutilisé dans plusieurs requêtes, dans le même processus php-fpm. Des suggestions sur la façon de faire cela? MISE À JOUR: J'ai essayé le diff suivant dans le code cluster_library.c mais cela semble provoquer des exceptions d'exécution aléatoires en php.phpredis Redis objets de connexion de cluster réutiliser à travers les demandes

index 3e532b7..b2cbf16 100644 
--- a/cluster_library.c 
+++ b/cluster_library.c 
@@ -7,6 +7,10 @@ 
#include <zend_exceptions.h> 

extern zend_class_entry *redis_cluster_exception_ce; 
+int cache_count = 0; 
+//Cache the cluster slots value for every n requests/calls, n being 100 for now 
+int CACHE_COUNT_VAL = 10; 
+clusterReply *permSlots=NULL; 

/* Debugging methods/ 
static void cluster_dump_nodes(redisCluster *c) { 
@@ -939,7 +943,18 @@ PHP_REDIS_API int cluster_map_keyspace(redisCluster *c TSRMLS_DC) { 
     } 

     // Parse out cluster nodes. Flag mapped if we are valid 
-  slots = cluster_get_slots(seed TSRMLS_CC); 
+ if (permSlots && cache_count <= CACHE_COUNT_VAL) { 
+   slots = permSlots; 
+   cache_count++; 
+ } 
+ else { 
+   slots = cluster_get_slots(seed TSRMLS_CC); 
+ } 
+ 
     if (slots) { 
      mapped = !cluster_map_slots(c, slots); 
      // Bin anything mapped, if we failed somewhere 
@@ -951,8 +966,16 @@ PHP_REDIS_API int cluster_map_keyspace(redisCluster *c TSRMLS_DC) { 
     if (mapped) break; 
    } ZEND_HASH_FOREACH_END(); 

+ if((!permSlots && mapped && slots) || 
+    cache_count >= CACHE_COUNT_VAL) { 
+ permSlots = slots; 
+ cache_count = 0; 
+ } 
+ 
    // Clean up slots reply if we got one 
- if(slots) cluster_free_reply(slots, 1); 
+ // if(slots) cluster_free_reply(slots, 1); 

    // Throw an exception if we couldn't map 
    if(!mapped) { 

Répondre

2

Développeur de phpredis ici. Il s'agit actuellement d'une limitation/faille dans phpredis car il doit émettre une commande CLUSTER SLOTS pour chaque nouvelle requête. Pour autant que je sache, la seule façon d'éviter cela est de pointer phpredis vers un proxy comme Codis ou Corvis mais je n'ai aucune expérience personnelle de les utiliser. Cela étant dit, j'ai implémenté un support expérimental pour cette fonctionnalité dans la branche this. Il utilise le code persistent_list de PHP pour mettre en cache les informations sur les emplacements entre les requêtes. Comme l'adoption de Redis Cluster semble s'accélérer, je vais essayer de l'intégrer bientôt dans la branche de développement Mainline et peut-être dans la prochaine version stable!

Cheers, Mike

+0

Merci Mike, cependant, j'ai essayé une solution simpliste en changeant commande cluster_map_keyspace de ne pas appeler cluster_get_slots (graines TSRMLS_CC); chaque fois et mettre en cache les emplacements dans une variable globale. J'ai aussi commenté cluster_free_reply (slots, 1) appel pour qu'il ne libère pas de mémoire slots. Cela fonctionne dans un scénario autonome, mais échoue dans l'installation de php-fpm + nginx. Des pensées sur pourquoi cela se passe-t-il? – sreeraag

+0

Oui, car le framework Zend dispose de son propre allocateur, qui nettoiera après vous si vous oubliez de libérer une variable. C'est pourquoi vous devez utiliser des éléments tels que persistate_list ou similaire afin de conserver le contexte entre les requêtes. Vous pourriez essayer d'allouer de la mémoire persistante (pemalloc) mais je ne le recommande pas. :) –

+0

Je n'avais aucune idée à ce sujet! Merci Mike! Mais cela fonctionne dans un script de test avec un processus php autonome mais échouait dans une configuration nginx + phpfpm, ce qui était étrange. Pourquoi ne recommanderiez-vous pas pemalloc? En outre, je pensais à la sérialisation de la réponse des emplacements de cluster à un fichier et à la récupération à partir du fichier à chaque fois. Pensez-vous que ce soit une bonne idée? Ou la branche qui utilise persist_list, je ne pense pas est mise en cache CLUSTER SLOTS hors de la boîte. Comment l'activer? – sreeraag