2017-05-31 4 views
0

J'essaie de comprendre la meilleure façon de mettre en œuvre la canalisation Redis. Nous utilisons redis comme cache au-dessus de MySQL pour stocker les données utilisateur, les listes de produits, etc. J'utilise ceci comme point de départ: https://joshtronic.com/2014/06/08/how-to-pipeline-with-phpredis/Redis pipeline, traitant des échecs de cache

Ma question est, en supposant que vous avez un tableau d'identifiants correctement triés. Vous boucle à travers le pipeline de Redis comme ceci:

$redis = new Redis(); 

// Opens up the pipeline 
$pipe = $redis->multi(Redis::PIPELINE); 

// Loops through the data and performs actions 
foreach ($users as $user_id => $username) 
{ 
    // Increment the number of times the user record has been accessed 
    $pipe->incr('accessed:' . $user_id); 

    // Pulls the user record 
    $pipe->get('user:' . $user_id); 
} 

// Executes all of the commands in one shot 
$users = $pipe->exec(); 

Qu'advient-il lorsque $pipe->get('user:' . $user_id); n'est pas disponible, parce qu'il n'a pas été demandé avant ou a été évincé par Redis, etc? En supposant que c'est le résultat n ° 13 de 50, comment avons-nous a) découvrir que nous n'avons pas pu récupérer cet objet et b) garder le tableau des utilisateurs correctement triés?

Merci

Répondre

2

Je vais répondre à la question concernant le protocole Redis. Comment cela fonctionne dans une langue particulière est plus ou moins la même chose dans ce cas. Tout d'abord, voyons comment fonctionne le pipeline Redis: C'est juste un moyen d'envoyer plusieurs commandes au serveur, de les exécuter et d'obtenir plusieurs réponses. Il n'y a rien de spécial, vous obtenez juste un tableau avec des réponses pour chaque commande dans le pipeline. Pourquoi les pipelines sont beaucoup plus rapides parce que le temps d'aller-retour pour chaque commande est sauvegardé, c'est-à-dire pour 100 commandes, il n'y a qu'un seul aller-retour au lieu de 100. De plus, Redis exécute chaque commande de manière synchrone. L'exécution de 100 commandes nécessite potentiellement 100 combats, pour que Redis choisisse cette commande singulière, le pipeline est traité comme une longue commande, ne nécessitant qu'une seule fois d'être sélectionné de manière synchrone.

Vous pouvez en savoir plus sur le pipelining ici: https://redis.io/topics/pipelining. Encore une remarque, parce que chaque batch pipelined s'exécute sans interruption (en termes de Redis), il est logique d'envoyer ces commandes en morceaux, par exemple n'envoyez pas 100k commandes dans un seul pipeline, qui pourrait bloquer Redis pendant une longue période, divisez-les en morceaux de commandes 1k ou 10k.

Dans votre cas, vous exécutez dans la boucle le fragment suivant:

// Increment the number of times the user record has been accessed 
$pipe->incr('accessed:' . $user_id); 

// Pulls the user record 
$pipe->get('user:' . $user_id); 

La question est ce qui est mis en pipeline? Supposons que vous mettiez à jour les données pour u1, u2, u3, u4 en tant qu'ID utilisateur. Ainsi, le pipeline avec Redis commandes ressemblera:

INCR accessed:u1 
GET user:u1 
INCR accessed:u2 
GET user:u2 
INCR accessed:u3 
GET user:u3 
INCR accessed:u4 
GET user:u4 

Disons que:

  • u1 a été consulté 100 fois avant,
  • u2 a été consulté 5 fois avant,
  • u3 n'a pas été consulté avant et
  • u4 et les données d'accompagnement n'existe pas.

Le résultat sera dans ce cas, un tableau de réponses Redis ayant:

101 
u1 string data stored at user:u1 
6 
u2 string data stored at user:u2 
1 
u3 string data stored at user:u3 
1 
NIL 

Comme vous pouvez le voir, Redis traitera les valeurs manquantes INCR comme 0 et exécuter incr(0).Enfin, rien n'est trié par Redis et les résultats viendront dans l'oder comme demandé.

La liaison de langue, par ex. Redis driver, va juste analyser pour vous ce protocole et donner la vue aux données analysées. Sans garder l'ordre des commandes, il sera impossible pour le pilote Redis de fonctionner correctement et pour vous, en tant que programmeur, d'en déduire la valeur. Gardez simplement à l'esprit que cette requête n'est pas dupliquée dans la réponse, c'est-à-dire que vous ne recevrez pas de clé pour u1 ou u2 lorsque vous faites GET, mais seulement les données pour cette clé. Ainsi, votre mise en œuvre doit se rappeler que sur la position 1 (zéro index) vient le résultat de GET pour u1.