2009-05-30 4 views
0

La configuration: Site Web à fort trafic et une liste d'URL d'images que nous voulons afficher. Nous avons un point d'image, et chaque élément de l'ensemble des URL d'images a un pourcentage d'affichage cible pour la journée. Exemple:Choix d'ensemble à fort pourcentage de trafic élevé?

  • Image1 - 10%
  • Image2 - 30%
  • Image3 - 60%

Parce que la quantité de trafic peut varier de jour en jour, je fais les pourcentages à l'intérieur blocs de 1000. Les images doivent également être prises au hasard, mais toujours correspondre à la distribution avec précision. Question: J'ai implémenté le code POC pour cela dans memcache, mais je ne suis pas à l'aise avec la façon dont les données sont stockées (plusieurs clés de hachage mappées par un "master record" avec des méta-données). Cela doit également pouvoir revenir à une base de données si les serveurs memcache tombent en panne. Je suis également préoccupé par les problèmes de concurrence pour la fiche principale.

Existe-t-il un moyen plus simple d'accomplir ceci? Peut-être une requête mysql rapide ou un meilleur moyen d'y introduire memcache?

Merci

+0

Je pense que vous n'avez reçu aucune réponse parce que votre problème n'est pas clair. – Galen

Répondre

0

Un coup à la base de données est plus susceptible de prendre plus de temps, je tiendrais donc avec memcache. Vous allez avoir plus de problèmes avec la concurrence en utilisant MySQL que memcache. memcache est mieux équipé pour gérer beaucoup de demandes et si les serveurs tombent en panne, ce sera le moindre de vos soucis sur un site web à fort trafic. Peut-être un expert MySQL peut-il canaliser ici avec une bonne structure de requête si vous nous donnez plus de détails.

1

Vous pouvez faire ce que vous avez dit, pregenerate un bloc de 1000 valeurs pointant les images que vous allez revenir:

$distribution = "011022201111202102100120 ..." # exactly evenly distributed 

stocker ensuite ce bloc dans MySQL et memcache, et utiliser une autre clé (dans les deux MySQL et memcache) pour contenir la valeur d'index actuelle pour la chaîne ci-dessus. Chaque fois que le script d'image est frappé, incrémenter la valeur dans memcache. Si memcache tombe en panne, allez à MySQL à la place (UPDATE, puis SELECT, il pourrait y avoir une meilleure façon de faire cette partie). Pour maintenir syncache et MySQL en synchronisation, vous pourriez avoir un travail cron copier la valeur d'index actuelle de memcache à MySQL. Vous allez perdre de la précision, mais cela peut ne pas être critique dans cette situation.

Vous pouvez stocker plusieurs distributions dans MySQL et memcache et avoir une autre clé qui pointe vers la distribution actuellement active. De cette façon, vous pouvez pré-générer de futurs blocs d'image. Lorsque l'index dépasse la distribution, le script incrémente la clé et passe à la suivante.

En gros:

function FetchImageFname() 
{ 
    $images = array(0 => 'image1.jpg', 1 => 'image2.jpg', 2 => 'image3.jpg'); 
    $distribution = FetchDistribution(); 
    $currentindex = FetchCurrentIndex(); 

    $x = 0; 
    while($distribution[$currentindex] == '' && $x < 10); 
    { 
    IncrementCurrentDistribKey(); 
    $distribution = FetchDistribution(); 
    $currentindex = FetchCurrentIndex(); 
    $x++; 
    } 

    if($distribution[$currentindex] == '') 
    { 
    // XXX Tried and failed. Send error to central logs. 
    return($images[0]); 
    } 

    return($distribution[$currentindex]); 
} 

function FetchDistribution() 
{ 
    $current_distib_key = FetchCurrentDistribKey(); 
    $distribution = FetchFromMemcache($current_distrib_key); 
    if(!$distribution) 
    $distribution = FetchFromMySQL($current_distrib_key); 
    return $distribution; 
} 

function FetchCurrentIndex() 
{ 
    $current_index = MemcacheIncrement('foo'); 
    if($current_index === false) 
    $current_index = MySQLIncrement('foo'); 
    return $current_index; 
} 

.. etc. Les noms de fonction type de puent, mais je pense que vous aurez l'idée. Lorsque le serveur memcache est de nouveau en mémoire, vous pouvez copier les données de MySQL vers memcache et il est instantanément réactivé.