Tactiques pour utiliser PHP dans un site à forte charge

242

Avant de répondre à cela, je n'ai jamais développé quelque chose d'assez populaire pour atteindre des charges de serveur élevées. Traitez-moi comme (soupir) un étranger qui vient d'atterrir sur la planète, même s'il connaît PHP et quelques techniques d'optimisation.


Je développe un outil en PHP qui pourrait atteindre un grand nombre d'utilisateurs, si cela fonctionne correctement. Cependant, bien que je sois pleinement capable de développer le programme, je suis quasiment désemparé lorsqu'il s'agit de créer quelque chose qui peut gérer un trafic énorme. Voici donc quelques questions à ce sujet (n'hésitez pas à transformer cette question en un fil de ressources également).

Bases de données

Pour le moment, je prévois d'utiliser les fonctionnalités de MySQLi en PHP5. Cependant, comment dois-je configurer les bases de données par rapport aux utilisateurs et au contenu? Ai-je réellement besoin de plusieurs bases de données? Pour le moment, tout est mélangé dans une base de données - bien que j'envisage de diffuser les données des utilisateurs dans une, le contenu réel dans une autre et enfin le contenu du site principal (modèles de modèles, etc.) dans une autre. Mon raisonnement derrière cela est que l'envoi de requêtes à différentes bases de données allégera la charge sur elles comme une base de données = 3 sources de charge. Cela serait-il également efficace s'ils étaient tous sur le même serveur?

Mise en cache

J'ai un système de modèle qui est utilisé pour créer les pages et échanger des variables. Les modèles principaux sont stockés dans la base de données et chaque fois qu'un modèle est appelé, sa copie en cache (un document html) est appelée. Pour le moment, j'ai deux types de variables dans ces modèles - une var statique et une var dynamique. Les variables statiques sont généralement des choses comme les noms de page, le nom du site - des choses qui ne changent pas souvent; les variables dynamiques sont des choses qui changent à chaque chargement de page.

Ma question à ce sujet:

Disons que j'ai des commentaires sur différents articles. Quelle est la meilleure solution: stocker le modèle de commentaire simple et rendre les commentaires (à partir d'un appel DB) chaque fois que la page est chargée ou stocker une copie mise en cache de la page de commentaires en tant que page html - chaque fois qu'un commentaire est ajouté / modifié / supprimé la page est recachée.

finalement

Quelqu'un at-il des conseils / pointeurs pour exécuter un site à haute charge sur PHP? Je suis sûr que c'est une langue utilisable à utiliser - Facebook et Yahoo! donnez-lui une grande priorité - mais y a-t-il des expériences à surveiller?

Ross
la source
9
3,5 ans plus tard et je ne me souviens même pas de ce sur quoi je travaillais, j'aimerais savoir ce que je pensais aussi cool :)
Ross
8
Que cela vous soit une leçon sur l'optimisation prématurée :)
Rimu Atkinson

Réponses:

89

Il n'y a pas deux sites identiques. Vous avez vraiment besoin d'un outil comme jmeter et benchmark pour voir où seront vos problèmes. Vous pouvez passer beaucoup de temps à deviner et à vous améliorer, mais vous ne verrez pas de résultats réels tant que vous n'aurez pas mesuré et comparé vos changements.

Par exemple, pendant de nombreuses années, le cache de requêtes MySQL a été la solution à tous nos problèmes de performances. Si votre site était lent, les experts MySQL ont suggéré d'activer le cache de requêtes. Il s'avère que si vous avez une charge d'écriture élevée, le cache est en fait paralysant. Si vous l'allumiez sans test, vous ne le sauriez jamais.

Et n'oubliez pas que vous n'avez jamais terminé la mise à l'échelle. Un site qui gère 10req / s devra être modifié pour prendre en charge 1000req / s. Et si vous êtes suffisamment lucking pour prendre en charge 10 000 req / s, votre architecture sera probablement complètement différente également.

Bases de données

  • N'utilisez pas MySQLi - PDO est la couche d'accès à la base de données OO «moderne». La fonctionnalité la plus importante à utiliser est les espaces réservés dans vos requêtes. Il est assez intelligent pour utiliser également les préparations côté serveur et d'autres optimisations.
  • Vous ne voulez probablement pas casser votre base de données à ce stade. Si vous constatez qu'une base de données ne coupe pas, il existe plusieurs techniques pour évoluer, en fonction de votre application. La réplication vers des serveurs supplémentaires fonctionne généralement bien si vous avez plus de lectures que d'écritures. Le sharding est une technique pour diviser vos données sur plusieurs machines.

Mise en cache

  • Vous ne voulez probablement pas mettre en cache dans votre base de données. La base de données est généralement votre goulot d'étranglement, donc y ajouter plus d'E / S est généralement une mauvaise chose. Il existe plusieurs caches PHP qui accomplissent des choses similaires comme APC et Zend.
  • Mesurez votre système en activant et désactivant la mise en cache. Je parie que votre cache est plus lourd que de servir les pages directement.
  • Si la création de vos commentaires et données d'article à partir de la base de données prend du temps, intégrez memcache dans votre système. Vous pouvez mettre en cache les résultats de la requête et les stocker dans une instance memcached. Il est important de se rappeler que la récupération des données de memcache doit être plus rapide que leur assemblage à partir de la base de données pour voir tout avantage.
  • Si vos articles ne sont pas dynamiques ou si vous avez des modifications dynamiques simples après leur génération, pensez à écrire du HTML ou du PHP sur le disque. Vous pourriez avoir une page index.php qui cherche sur le disque pour l'article, si elle est là, elle le diffuse au client. Si ce n'est pas le cas, il génère l'article, l'écrit sur le disque et l'envoie au client. La suppression de fichiers du disque entraînerait la réécriture des pages. Si un commentaire est ajouté à un article, supprimez la copie mise en cache - elle serait régénérée.
Gary Richardson
la source
10
@ écrire sur le disque. Vous pouvez même abandonner index.php et laisser Apache faire le travail pour vous, afin que index.php ne soit appelé que si le chemin n'existe pas. Vous utiliseriez mode_rewrite pour cela.
troelskn
5
-1, PDO est beaucoup plus lent que MySQLi ou même l'extension MySQL.
Alix Axel
4
PDO était beaucoup plus lent que mysqli et ne fonctionnait pas correctement pour les requêtes imbriquées. Mysqli prend également en charge la préparation côté serveur et les paramètres liés, tout comme PDO.
Daren Schwenke
5
Je ne peux pas croire que cela ait été accepté comme réponse. Ce n'est pas très bon.
symcbean
1
about: mise en cache - les images, css, htm et js vous aideront, désactivez également les cookies sur les images!
Talvi Watia
61

Je suis développeur principal sur un site de plus de 15 millions d'utilisateurs. Nous avons eu très peu de problèmes de mise à l'échelle parce que nous l'avons planifié TÔT et mis à l'échelle de manière réfléchie. Voici quelques-unes des stratégies que je peux suggérer de mon expérience.

SCHEMA Tout d'abord, dénormalisez vos schémas. Cela signifie que plutôt que d'avoir plusieurs tables relationnelles, vous devriez plutôt choisir d'avoir une grande table. En général, les jointures sont un gaspillage de précieuses ressources de base de données, car plusieurs préparations et collations brûlent les E / S de disque. Évitez-les lorsque vous le pouvez.

Le compromis ici est que vous stockerez / tirerez des données redondantes, mais cela est acceptable car les données et la bande passante intra-cage sont très bon marché (disques plus gros) tandis que les multiples E / S préparées sont des ordres de grandeur plus chers (plus de serveurs) .

INDEXATION Assurez-vous que vos requêtes utilisent au moins un index. Attention cependant, ces index vous coûteront si vous écrivez ou mettez à jour fréquemment. Il existe quelques astuces expérimentales pour éviter cela.

Vous pouvez essayer d'ajouter des colonnes supplémentaires non indexées qui s'exécutent parallèlement à vos colonnes indexées. Ensuite, vous pouvez avoir un processus hors ligne qui écrit les colonnes non indexées sur les colonnes indexées par lots. De cette façon, vous pouvez mieux contrôler quand mySQL devra recalculer l'index.

Évitez les requêtes calculées comme une peste. Si vous devez calculer une requête, essayez de le faire une fois au moment de l'écriture.

CACHING Je recommande fortement Memcached. Il a été prouvé par les plus grands acteurs de la pile PHP (Facebook) et est très flexible. Il existe deux méthodes pour ce faire, l'une consiste à mettre en cache dans votre couche DB, l'autre à mettre en cache dans votre couche logique métier.

L'option de couche DB nécessiterait la mise en cache du résultat des requêtes récupérées à partir de la base de données. Vous pouvez hacher votre requête SQL à l'aide de md5 () et l'utiliser comme clé de recherche avant d'accéder à la base de données. L'avantage est qu'il est assez facile à mettre en œuvre. L'inconvénient (selon l'implémentation) est que vous perdez de la flexibilité car vous traitez tous les caches de la même manière en ce qui concerne l'expiration du cache.

Dans la boutique dans laquelle je travaille, nous utilisons la mise en cache de la couche métier, ce qui signifie que chaque classe concrète de notre système contrôle son propre schéma de mise en cache et ses délais d'expiration. Cela a plutôt bien fonctionné pour nous, mais sachez que les éléments récupérés de la base de données peuvent ne pas être identiques aux éléments du cache, vous devrez donc mettre à jour le cache et la base de données ensemble.

SUPPRESSION DES DONNÉES La réplication ne vous permet pour l'instant. Plus tôt que prévu, vos écritures deviendront un goulot d'étranglement. Pour compenser, assurez-vous de prendre en charge le partage des données le plus tôt possible. Vous voudrez probablement vous tirer dessus plus tard si vous ne le faites pas.

C'est assez simple à mettre en œuvre. Fondamentalement, vous souhaitez séparer l'autorité clé du stockage de données. Utilisez une base de données globale pour stocker un mappage entre les clés primaires et les ID de cluster. Vous interrogez ce mappage pour obtenir un cluster, puis interrogez le cluster pour obtenir les données. Vous pouvez mettre l'enfer hors de cette opération de recherche, ce qui en fera une opération négligeable.

L'inconvénient est qu'il peut être difficile de rassembler les données de plusieurs fragments. Mais, vous pouvez également vous en sortir.

TRAITEMENT HORS LIGNE Ne faites pas attendre l'utilisateur pour votre backend s'il n'y est pas obligé. Créez une file d'attente de travaux et déplacez tout traitement que vous pouvez déconnecter, en le faisant séparément de la demande de l'utilisateur.

thesmart
la source
9
+1 haut la main, cela devrait être la réponse acceptée. Il est intéressant de noter que tout ce que j'ai lu sur la création de bases de données dit toujours "normaliser toutes les données autant que possible" sans mentionner les performances des jointures. J'ai toujours pensé intuitivement que les jointures (en particulier les jointures multiples) ajoutaient beaucoup de frais généraux, mais je n'en ai entendu aucun dire explicitement jusqu'à présent. Je souhaite avoir mieux compris ce que vous parliez de contrôler lorsque MySQL calcule les index, cela ressemble à un hack très intéressant.
Evan Plaice
Le partage des données est essentiel pour les bases de données trop volumineuses. Google (l'entreprise n'est pas le moteur de recherche) a beaucoup de choses intéressantes à dire sur la mise en œuvre de schémas de partage. Le traitement hors ligne est également énorme lorsqu'il s'agit de limiter le nombre d'écritures de base de données (et de limiter le nombre de recalculs d'index de table). J'ai vu de nombreux blogs (et je pense même Stack Overflow) utiliser cette technique pour leurs systèmes de commentaires / commentaires générés par les utilisateurs.
Evan Plaice
1
Merci pour les commentaires. Il est étonnant que certains plaident pour le profilage du code de niveau intermédiaire lorsque le temps d'exécution VAST est passé dans les E / S de données ou les E / S client-serveur. Une optimisation ubber compliquée permettant d'économiser 20% sur le temps d'exécution d'un processus PHP qui prend 40 ms est inutile par rapport à une simple économie de 5% sur une requête de base de données 1s.
thesmart
42

J'ai travaillé sur quelques sites qui obtiennent des millions / hits / mois soutenus par PHP et MySQL. Voici quelques notions de base:

  1. Cache, cache, cache. La mise en cache est l'un des moyens les plus simples et les plus efficaces de réduire la charge de votre serveur Web et de votre base de données. Cachez le contenu de la page, les requêtes, les calculs coûteux, tout ce qui est lié aux E / S. Memcache est mort simple et efficace.
  2. Utilisez plusieurs serveurs une fois que vous êtes au maximum. Vous pouvez avoir plusieurs serveurs Web et plusieurs serveurs de bases de données (avec réplication).
  3. Réduisez le nombre total de demandes adressées à vos serveurs Web. Cela implique la mise en cache de JS, CSS et des images à l'aide d'en-têtes expirés. Vous pouvez également déplacer votre contenu statique vers un CDN, ce qui accélérera l'expérience de votre utilisateur.
  4. Mesurer et comparer. Exécutez Nagios sur vos machines de production et testez la charge sur votre serveur dev / qa. Vous devez savoir quand votre serveur prendra feu afin de pouvoir l'empêcher.

Je recommanderais de lire des sites Web évolutifs , il a été écrit par l'un des ingénieurs de Flickr et est une excellente référence.

Consultez également mon article de blog sur l'évolutivité, il contient de nombreux liens vers des présentations sur l'évolutivité avec plusieurs langues et plates-formes: http://www.ryandoherty.net/2008/07/13/unicorns-and-scalability/

Ryan Doherty
la source
1
+1 Il y a beaucoup de bonnes informations ici. J'ai fait plus de recherches sur ce sujet récemment et votre réponse est conforme à tout ce que j'ai lu. Memcache, mise en cache, CDN pour le contenu statique, réduction des demandes; toutes les bonnes choses. Je voudrais également ajouter, générer des hachages sur les fichiers de contenu statiques (si vous êtes derrière un CDN / cache) côté serveur afin que les fichiers mis à jour aient une signature unique dans le cache. Combinez également les fichiers sources statiques (css, javascript) à la volée (et mettez-les en cache avec des hachages de nom de fichier) pour réduire les demandes. Générez également des pouces dynamiquement (et stockez-les dans le cache)
Evan Plaice
Google a créé un module apache appelé mod_pagespeed qui peut gérer toutes les concaténations de fichiers, la minification, le renommage de fichiers pour inclure le hachage, etc. pour tout le contenu statique. Cela ne devrait initialement ajouter qu'une petite surcharge de traitement aux serveurs jusqu'à ce que les caches (et les CDN) soient remplis avec la plupart du contenu. De plus, pour des raisons de sécurité, c'est généralement une mauvaise idée de mettre des tables accessibles au public (utilisateurs) dans la même base de données que les tables que de gérer le back-end (si pour une raison quelconque l'une des tables devait être piratée).
Evan Plaice
39

Re: PDO / MySQLi / MySQLND

@ gary

Vous ne pouvez pas simplement dire "n'utilisez pas MySQLi" car ils ont des objectifs différents. PDO est presque comme une couche d'abstraction (bien qu'il ne le soit pas réellement) et est conçu pour faciliter l'utilisation de plusieurs produits de base de données alors que MySQLi est spécifique aux connexions MySQL. Il est faux de dire que PDO est la couche d'accès moderne dans le contexte de sa comparaison avec MySQLi car votre déclaration implique que la progression a été mysql -> mysqli -> PDO ce qui n'est pas le cas.

Le choix entre MySQLi et PDO est simple - si vous devez prendre en charge plusieurs produits de base de données, vous utilisez PDO. Si vous utilisez simplement MySQL, vous pouvez choisir entre PDO et MySQLi.

Alors pourquoi choisir MySQLi plutôt que PDO? Voir ci-dessous...

@ross

Vous avez raison au sujet de MySQLnd qui est la plus récente bibliothèque de niveau de langage de base MySQL, mais elle ne remplace pas MySQLi. MySQLi (comme avec PDO) reste la façon dont vous interagissez avec MySQL via votre code PHP. Les deux utilisent libmysql comme client C derrière le code PHP. Le problème est que libmysql est en dehors du moteur PHP principal et c'est là que mysqlnd entre en scène, c'est-à-dire qu'il s'agit d'un pilote natif qui utilise les internes PHP principaux pour maximiser l'efficacité, en particulier en ce qui concerne l'utilisation de la mémoire.

MySQLnd est développé par MySQL lui-même et a récemment atterri sur la branche PHP 5.3 qui est en test RC, prête pour une sortie plus tard cette année. Vous pourrez alors utiliser MySQLnd avec MySQLi ... mais pas avec PDO. Cela donnera à MySQLi une amélioration des performances dans de nombreux domaines (pas tous) et en fera le meilleur choix pour l'interaction MySQL si vous n'avez pas besoin des capacités d'abstraction de PDO.

Cela dit, MySQLnd est désormais disponible en PHP 5.3 pour PDO et vous pouvez donc profiter des avantages des améliorations de performances de ND en PDO, cependant, PDO est toujours une couche de base de données générique et il est donc peu probable qu'il puisse en bénéficier autant. les améliorations dans ND comme MySQLi peut .

Certains repères utiles peuvent être trouvés ici bien qu'ils datent de 2006. Vous devez également être conscient de choses comme cette option .

Il y a beaucoup de considérations qui doivent être prises en compte lors du choix entre MySQLi et PDO. En réalité, cela n'aura pas d'importance tant que vous n'atteindrez pas un nombre de demandes extrêmement élevé et dans ce cas, il est plus logique d'utiliser une extension spécialement conçue pour MySQL plutôt qu'une extension qui résume les choses et fournit un pilote MySQL. .

Ce n'est pas une question simple qui est la meilleure, car chacune a ses avantages et ses inconvénients. Vous devez lire les liens que j'ai fournis et prendre votre propre décision, puis la tester et la découvrir. J'ai utilisé PDO dans des projets antérieurs et c'est une bonne extension mais mon choix pour des performances pures serait MySQLi avec la nouvelle option MySQLND compilée (lorsque PHP 5.3 est sorti).

davidmytton
la source
6
Je suis passé de PDO à mysqli et les requêtes régulières ont commencé à s'exécuter exactement 2 fois plus rapidement.
serg
5
@serg: attention à poster des tests pour le confirmer?, car je doute sérieusement que le simple passage de PDO à mysqli vous donne un tel boost de vitesse.
Stann
23

Général

  • N'essayez pas d'optimiser avant de commencer à voir la charge du monde réel. Vous devinez peut-être bien, mais si vous ne le faites pas, vous avez perdu votre temps.
  • Utilisez jmeter , xdebug ou un autre outil pour comparer le site.
  • Si la charge commence à être un problème, la mise en cache d'objets ou de données sera probablement impliquée, donc lisez généralement les options de mise en cache (memcached, options de mise en cache MySQL)

Code

  • Profilez votre code afin de savoir où se trouve le goulot d'étranglement et s'il se trouve dans le code ou dans la base de données

Bases de données

  • Utilisez MYSQLi si la portabilité vers d'autres bases de données n'est pas indispensable, sinon PDO
  • Si les tests de performance révèlent que la base de données est le problème, vérifiez les requêtes avant de commencer la mise en cache. Utilisez EXPLAIN pour voir où vos requêtes ralentissent.
  • Une fois les requêtes optimisées et la base de données mise en cache d'une manière ou d'une autre, vous souhaiterez peut-être utiliser plusieurs bases de données. La réplication sur plusieurs serveurs ou le partitionnement (fractionnement des données sur plusieurs bases de données / serveurs) peut être approprié, selon les données, les requêtes et le type de comportement en lecture / écriture.

Mise en cache

  • Beaucoup d'écriture a été faite sur la mise en cache du code, des objets et des données. Recherchez des articles sur APC , Zend Optimizer , memcached , QuickCache , JPCache . Faites-en une partie avant d'en avoir vraiment besoin, et vous serez moins préoccupé par un démarrage non optimisé.
  • APC et Zend Optimizer sont des caches d'opcode, ils accélèrent le code PHP en évitant une nouvelle analyse et une recompilation du code. Généralement simple à installer, vaut la peine d'être fait tôt.
  • Memcached est un cache générique que vous pouvez utiliser pour mettre en cache des requêtes, des fonctions ou des objets PHP ou des pages entières. Le code doit être spécifiquement écrit pour l'utiliser, ce qui peut être un processus impliqué s'il n'y a pas de points centraux pour gérer la création, la mise à jour et la suppression des objets mis en cache.
  • QuickCache et JPCache sont des caches de fichiers, sinon similaires à Memcached. Le concept de base est simple, mais nécessite également du code et est plus facile avec les points centraux de création, de mise à jour et de suppression.

Divers

  • Envisagez des serveurs Web alternatifs pour une charge élevée. Des serveurs comme lighthttp et nginx peuvent gérer de grandes quantités de trafic dans beaucoup moins de mémoire qu'Apache , si vous pouvez sacrifier la puissance et la flexibilité d'Apache (ou si vous n'avez tout simplement pas besoin de ces choses, ce qui souvent, vous n'avez pas).
  • N'oubliez pas que le matériel est étonnamment bon marché de nos jours, alors assurez-vous de dépenser l'effort d'optimiser un gros bloc de code par rapport à «achetons un serveur monstre».
  • Pensez à ajouter les balises "MySQL" et "scaling" à cette question
Paul Kroll
la source
9

APC est un must absolu. Non seulement il constitue un excellent système de mise en cache, mais le gain des fichiers PHP mis en cache automatiquement est une aubaine. En ce qui concerne l'idée de bases de données multiples, je ne pense pas que vous tireriez beaucoup d'avantages d'avoir différentes bases de données sur le même serveur. Cela peut vous donner un peu de gain de vitesse pendant le temps de requête, mais je doute que l'effort qu'il faudrait pour déployer et maintenir le code pour les trois tout en s'assurant qu'ils soient synchronisés en vaudrait la peine.

Je recommande également fortement d'exécuter Xdebug pour trouver des goulots d'étranglement dans votre programme. Cela a fait de l'optimisation un jeu d'enfant pour moi.

tslocum
la source
9

Premièrement, comme je pense que Knuth l'a dit, "l'optimisation prématurée est la racine de tout mal". Si vous n'avez pas à résoudre ces problèmes pour l'instant, ne le faites pas, concentrez-vous d'abord sur la livraison de quelque chose qui fonctionne correctement. Cela étant dit, si les optimisations ne peuvent pas attendre.

Essayez de profiler vos requêtes de base de données, déterminez ce qui est lent et ce qui se passe beaucoup et trouvez une stratégie d'optimisation à partir de cela.

J'enquêterais sur Memcached car c'est ce que beaucoup de sites à plus forte charge utilisent pour mettre en cache efficacement le contenu de tous types, et l'interface d'objet PHP est assez agréable.

La répartition des bases de données entre les serveurs et l'utilisation d'une sorte de technique d'équilibrage de charge (par exemple, générer un nombre aléatoire entre 1 et # bases de données redondantes avec les données nécessaires - et utiliser ce nombre pour déterminer à quel serveur de base de données se connecter) peut également être un excellent moyen d'augmenter Efficacité.

Ceux-ci ont tous très bien fonctionné dans le passé pour certains sites de charge assez élevée. J'espère que cela vous aidera à démarrer :-)

Eric Scrivner
la source
1
RequiredFullQuote: "Nous devons oublier les petites efficacités, disons environ 97% du temps: l'optimisation prématurée est la racine de tout mal"
Alister Bulman
RequiredReallyFullQuote: "Les programmeurs perdent énormément de temps à penser ou à s'inquiéter de la vitesse des parties non critiques de leurs programmes, et ces tentatives d'efficacité ont en fait un fort impact négatif lors du débogage et de la maintenance. Nous devons oublier les petites économies, disent environ 97% du temps: l'optimisation prématurée est la racine de tout mal. Pourtant, nous ne devons pas laisser passer nos opportunités dans ces 3% critiques. "
cHao
6

Le profilage de votre application avec quelque chose comme Xdebug (comme tj9991 recommandé) sera certainement un must. Cela n'a pas beaucoup de sens de simplement optimiser les choses aveuglément. Xdebug vous aidera à trouver les vrais goulots d'étranglement dans votre code afin que vous puissiez passer votre temps d'optimisation à bon escient et corriger des morceaux de code qui causent des ralentissements.

Si vous utilisez Apache, Siege est un autre utilitaire qui peut vous aider lors des tests . Il vous aidera à anticiper la réaction de votre serveur et de votre application à des charges élevées en le mettant vraiment à l'épreuve.

Tout type de cache d'opcode pour PHP (comme APC ou l'un des nombreux autres) sera également très utile.

Bob Somers
la source
6

Je gère un site Web avec 7 à 8 millions de pages vues par mois. Pas terriblement, mais suffisamment pour que notre serveur ait senti la charge. La solution que nous avons choisie était simple: Memcache au niveau de la base de données. Cette solution fonctionne bien si la charge de la base de données est votre principal problème.

Nous avons commencé par utiliser Memcache pour mettre en cache des objets entiers et les résultats de la base de données les plus fréquemment utilisés. Cela a fonctionné, mais il a également introduit des bogues (nous aurions pu en éviter certains si nous avions été plus prudents).

Nous avons donc changé notre approche. Nous avons construit un wrapper de base de données (avec exactement les mêmes méthodes que notre ancienne base de données, il était donc facile de changer), puis nous l'avons sous-classé pour fournir des méthodes d'accès à la base de données memcached.

Il ne vous reste plus qu'à décider si une requête peut utiliser ou non les résultats mis en cache (et éventuellement obsolètes). La plupart des requêtes exécutées par les utilisateurs sont désormais récupérées directement depuis Memcache. Les exceptions sont les mises à jour et les insertions, qui ne se produisent pour le site Web principal qu'en raison de la journalisation. Cette mesure assez simple a réduit notre charge de serveur d'environ 80%.

Vegard Larsen
la source
6

Pour ce que ça vaut, la mise en cache est DIRT SIMPLE en PHP même sans package d'extension / d'assistance comme memcached.

Il vous suffit de créer un tampon de sortie à l'aide de ob_start().

Créez une fonction de cache globale. Appelez ob_start, passez la fonction comme rappel. Dans la fonction, recherchez une version en cache de la page. S'il existe, servez-le et terminez.

S'il n'existe pas, le script continuera son traitement. Quand il atteint l'ob_end () correspondant, il appellera la fonction que vous avez spécifiée. À ce moment-là, vous obtenez simplement le contenu du tampon de sortie, les déposez dans un fichier, enregistrez le fichier et terminez.

Ajoutez une certaine expiration / garbage collection.

Et beaucoup de gens ne réalisent pas que vous pouvez imbriquer ob_start()/ ob_end()appeler. Donc, si vous utilisez déjà un tampon de sortie pour, par exemple, analyser des publicités ou faire de la coloration syntaxique ou autre, vous pouvez simplement imbriquer un autre ob_start/ob_endappel.

UN J
la source
+1 car cela ressemble à une idée intéressante. Je ne sais pas si cela fonctionne bien en
termes de
+1 parce que c'est une idée intéressante. Ces rappels pourraient appeler ma classe de mise en cache pour moi!
Xeoncross
5

Merci pour les conseils sur les extensions de mise en cache de PHP - pourriez-vous expliquer les raisons de l'utilisation l'une sur l'autre? J'ai entendu beaucoup de choses sur memcached via IRC mais je n'ai jamais entendu parler d'APC - quelles sont vos opinions à leur sujet? Je suppose que l'utilisation de plusieurs systèmes de mise en cache est assez contre-efficace.

En fait, beaucoup utilisent APC et memcached ensemble ...

ceejayoz
la source
4

On dirait que j'avais tort . MySQLi est toujours en cours de développement. Mais selon l'article, PDO_MySQL est désormais contribué par l'équipe MySQL. De l'article:

L'extension améliorée MySQL - mysqli - est le produit phare. Il prend en charge toutes les fonctionnalités du serveur MySQL, y compris les jeux de caractères, les instructions préparées et les procédures stockées. Le pilote propose une API hybride: vous pouvez utiliser un style de programmation procédural ou orienté objet en fonction de vos préférences. mysqli est livré avec PHP 5 et plus. Notez que la fin de vie de PHP 4 est le 2008-08-08.

Les objets de données PHP (PDO) sont une couche d'abstraction d'accès à la base de données. PDO vous permet d'utiliser les mêmes appels d'API pour différentes bases de données. PDO n'offre aucun degré d'abstraction SQL. PDO_MYSQL est un pilote MySQL pour PDO. PDO_MYSQL est livré avec PHP 5. Depuis PHP 5.3, les développeurs MySQL y contribuent activement. L'avantage PDO d'une API unifiée vient au prix que les fonctionnalités spécifiques à MySQL, par exemple plusieurs instructions, ne sont pas entièrement prises en charge via l'API unifiée.

Veuillez cesser d'utiliser le premier pilote MySQL pour PHP jamais publié: ext / mysql. Depuis l'introduction de l'extension améliorée MySQL - mysqli - en 2004 avec PHP 5, il n'y a aucune raison d'utiliser toujours le pilote le plus ancien. ext / mysql ne prend pas en charge les jeux de caractères, les instructions préparées et les procédures stockées. Il est limité à l'ensemble des fonctionnalités de MySQL 4.0. Notez que la prise en charge étendue de MySQL 4.0 se termine le 2008-12-31. Ne vous limitez pas à l'ensemble des fonctionnalités de ces anciens logiciels! Passez à mysqli, voir aussi Converting_to_MySQLi. mysql est en mode maintenance uniquement de notre point de vue.

Pour moi, il semble que l'article soit biaisé vers MySQLi. Je suppose que je suis partisan de l'AOP. J'aime vraiment PDO sur MySQLi. C'est simple pour moi. L'API est beaucoup plus proche des autres langages que j'ai programmés. Les interfaces de base de données OO semblent mieux fonctionner.

Je n'ai pas rencontré de fonctionnalités MySQL spécifiques qui n'étaient pas disponibles via PDO. Je serais surpris si jamais je le faisais.

Gary Richardson
la source
3

PDO est également très lent et son API est assez compliquée. Personne dans leur esprit ne devrait l'utiliser si la portabilité n'est pas un problème. Et avouons-le, dans 99% de toutes les applications Web, ce n'est pas le cas. Vous vous en tenez à MySQL ou PostrgreSQL, ou quoi que ce soit avec lequel vous travaillez.

Quant à la question PHP et ce qu'il faut prendre en compte. Je pense que l'optimisation prématurée est la racine de tout mal. ;) Faites d'abord votre application, essayez de la garder propre quand il s'agit de programmation, faites un peu de documentation et écrivez des tests unitaires. Avec tout ce qui précède, vous n'aurez aucun problème à refactoriser le code le moment venu. Mais d'abord, vous voulez en finir et pousser pour voir comment les gens y réagissent.

Jusqu'à
la source
2

Bien sûr, pdo est sympa, mais il y a eu une controverse sur ses performances par rapport à mysql et mysqli, bien qu'il semble fixe maintenant.

Vous devriez utiliser pdo si vous envisagez la portabilité, mais sinon, mysqli devrait être le chemin. Il a une interface OO, des instructions préparées et la plupart de ce que pdo offre (sauf, bien, la portabilité).

De plus, si les performances sont vraiment nécessaires, préparez-vous au pilote MysqLnd (mysql natif) en PHP 5.3, qui sera beaucoup plus étroitement intégré à php, avec de meilleures performances et une meilleure utilisation de la mémoire (et des statistiques pour le réglage des performances).

Memcache est bien si vous avez des serveurs en cluster (et une charge similaire à YouTube), mais j'essaierais d'abord APC aussi.

Berzemus
la source
2

Beaucoup de bonnes réponses ont déjà été données, mais je voudrais vous indiquer un autre cache d'opcode appelé XCache . Il est créé par un contributeur léger.

De plus, si vous avez besoin d'équilibrer la charge de votre serveur de base de données à l'avenir, MySQL Proxy pourrait très bien vous aider à y parvenir.

Ces deux outils devraient se connecter assez facilement à une application existante, afin que cette optimisation puisse être effectuée lorsque vous en avez besoin, sans trop de tracas.

hangy
la source
2

La première question est de savoir quelle taille vous attendez-vous vraiment à avoir? Et combien prévoyez-vous d'investir dans votre infrastructure? Puisque vous ressentez le besoin de poser la question ici, je suppose que vous vous attendez à commencer petit avec un budget limité.

Les performances ne sont pas pertinentes si le site n'est pas disponible. Et pour la disponibilité, vous avez besoin d'une mise à l'échelle horizontale. Le minimum avec lequel vous pouvez raisonnablement vous éloigner est de 2 serveurs, tous deux exécutant apache, php et mysql. Configurez un SGBD comme esclave de l'autre. Faites toutes les écritures sur le maître et toutes les lectures sur la base de données locale (quelle qu'elle soit) - sauf si pour une raison quelconque vous devez relire les données que vous venez de lire (utilisez le maître). Assurez-vous que vous avez les machines en place pour promouvoir automatiquement l'esclave et clôturer le maître. Utilisez le DNS à tour de rôle pour les adresses de serveur Web pour donner plus d'affinité au nœud esclave.

Le partitionnement de vos données sur différents nœuds de base de données à ce stade est une très mauvaise idée, mais vous voudrez peut-être envisager de les diviser entre différentes bases de données sur le même serveur (ce qui facilitera le partitionnement entre les nœuds lorsque vous dépasserez Facebook).

Assurez-vous que vous disposez des outils de surveillance et d'analyse des données pour mesurer les performances de vos sites et identifier les goulots d'étranglement. La plupart des problèmes de performances peuvent être résolus en écrivant mieux SQL / en réparant le schéma de la base de données.

Garder le cache de votre modèle sur la base de données est une idée stupide - la base de données devrait être un référentiel commun central pour les données structurées. Conservez le cache de votre modèle sur le système de fichiers local de vos serveurs Web - il sera disponible plus rapidement et ne ralentira pas l'accès à votre base de données.

Utilisez un cache de code op.

Passez beaucoup de temps à étudier votre site et ses journaux pour comprendre pourquoi cela va si lentement.

Poussez autant de cache que possible sur le client.

Utilisez mod_gzip pour compresser tout ce que vous pouvez.

C.

symcbean
la source
2

Mon premier conseil est de penser à ce problème et de le garder à l'esprit lors de la conception du site, mais n'allez pas trop loin . Il est souvent difficile de prédire le succès d'un nouveau site et je ferai mieux de consacrer votre temps à vous lever tôt et à l'optimiser plus tard.

En général, Simple est rapide . Les modèles vous ralentissent. Les bases de données vous ralentissent. Les bibliothèques complexes vous ralentissent. Superposition de modèles les uns sur les autres, récupération des bases de données et analyse dans une bibliothèque complexe -> les délais se multiplient les uns avec les autres.

Une fois que le site de base est opérationnel, faites des tests pour vous montrer où dépenser vos efforts. Il est difficile de voir où viser. Souvent, pour accélérer les choses, vous devrez démêler la complexité du code, ce qui le rend plus volumineux et plus difficile à maintenir, vous ne voulez donc le faire que si nécessaire.

D'après mon expérience, l'établissement de la connexion à la base de données était relativement coûteux. Si vous pouvez vous en sortir, ne vous connectez pas à la base de données pour les visiteurs généraux sur les pages les plus fréquentées comme la première page du site. Créer plusieurs connexions à des bases de données est une folie avec très peu d'avantages.

lod
la source
1

@ Gary

N'utilisez pas MySQLi - PDO est la couche d'accès à la base de données OO «moderne». La fonctionnalité la plus importante à utiliser est les espaces réservés dans vos requêtes. Il est assez intelligent pour utiliser également les préparations côté serveur et d'autres optimisations.

Je suis en train de me pencher sur PDO pour le moment et il semble que vous ayez raison - cependant je sais que MySQL développe l'extension MySQLd pour PHP - je pense que pour réussir MySQL ou MySQLi - qu'en pensez-vous?


@ Ryan , Eric , tj9991

Merci pour les conseils sur les extensions de mise en cache de PHP - pourriez-vous expliquer les raisons de l'utilisation l'une sur l'autre? J'ai entendu beaucoup de choses sur memcached via IRC mais je n'ai jamais entendu parler d'APC - quelles sont vos opinions à leur sujet? Je suppose que l'utilisation de plusieurs systèmes de mise en cache est assez contre-efficace.

Je vais certainement trier certains testeurs de profilage - merci beaucoup pour vos recommandations à ce sujet.

Ross
la source
1

Je ne me vois pas passer de MySQL de sitôt - donc je suppose que je n'ai pas besoin des capacités d'abstraction de PDO. Merci pour ces articles DavidM, ils m'ont beaucoup aidé.

Ross
la source
1

Examinez mod_cache , un cache de sortie pour le serveur Web Apache, similaire à la mise en cache de sortie dans ASP.NET.

Oui, je vois que c'est encore expérimental mais ce sera définitif un jour.

Andrei Rînea
la source
1

Je ne peux pas croire que personne ne l'ait déjà mentionné: Modularisation et Abstraction. Si vous pensez que votre site va devoir évoluer vers de nombreuses machines, vous devez le concevoir pour qu'il le puisse! Cela signifie des choses stupides comme ne supposez pas que la base de données est sur localhost. Cela signifie également des choses qui vont être gênantes au début, comme l'écriture d'une couche d'abstraction de base de données (comme PDO, mais beaucoup plus légère car elle ne fait que ce dont vous avez besoin).

Et cela signifie des choses comme travailler avec un framework. Vous aurez besoin de couches pour votre code afin de pouvoir gagner des performances ultérieurement en refactorisant la couche d'abstraction des données, par exemple, en lui apprenant que certains objets se trouvent dans une base de données différente - et que le code n'a pas besoin de connaître ou de prendre soin .

Enfin, faites attention aux opérations gourmandes en mémoire, par exemple, la copie inutile de chaînes. Si vous pouvez réduire l'utilisation de la mémoire de PHP, vous obtiendrez plus de performances de votre serveur Web et c'est quelque chose qui évoluera lorsque vous passerez à une solution à charge équilibrée.

staticien
la source
1

Si vous travaillez avec de grandes quantités de données et que la mise en cache ne les coupe pas, examinez Sphinx. Nous avons obtenu d'excellents résultats en utilisant SphinxSearch non seulement pour une meilleure recherche de texte, mais aussi comme remplacement de récupération de données pour MySQL lors de l'utilisation de tables plus grandes. Si vous utilisez SphinxSE (plug-in MySQL), il a dépassé nos gains de performances que nous avons obtenus à plusieurs reprises en cache, et la mise en œuvre de l'application est un sinch.


la source
1

Les remarques sur le cache sont parfaites; c'est la partie la moins compliquée et la plus importante de la construction d'une application efficace. Je voudrais ajouter que même si memcached est génial, APC est environ cinq fois plus rapide si votre application vit sur un seul serveur.

Le post "Comparaison des performances du cache" sur le blog des performances de MySQL contient des références intéressantes sur le sujet - http://www.mysqlperformanceblog.com/2006/08/09/cache-performance-comparison/ .

Johannes Gorset
la source