Après avoir parlé de l'environnement réseau externe du système Web, nous commençons maintenant à nous concentrer sur les problèmes de performances de notre système Web lui-même.
À mesure que le nombre de visites sur notre site Web augmente, nous serons confrontés à de nombreux défis. Résoudre ces problèmes n'est pas aussi simple que d'étendre la machine, mais établir et utiliser un mécanisme de mise en cache approprié est fondamental.
Au début, l'architecture de notre système Web peut être comme ceci. Chaque lien ne peut avoir qu'une seule machine.
1. En utilisant le cache interne de la base de données MySQL
Le mécanisme de mise en cache de MySQL, commençons par le cache interne de MySQL, le contenu suivant Il sera basé sur le moteur de stockage InnoDB le plus courant.
1. Établir des index appropriés
Le plus simple est de créer un index Lorsque les données de la table sont relativement volumineuses, l'index peut récupérer rapidement les données, mais le coût y est. il y en a aussi. Tout d'abord, il occupe une certaine quantité d'espace disque. Parmi eux, l'index combiné est le plus important. Il doit être utilisé avec prudence. L'index qu'il génère peut même être plus grand que les données source. Deuxièmement, les opérations telles que l'insertion/la mise à jour/la suppression de données après la création de l'index prendront plus de temps car l'index d'origine doit être mis à jour. Bien entendu, en fait, notre système dans son ensemble est dominé par des opérations de requête sélectionnées. Par conséquent, l'utilisation d'index peut encore améliorer considérablement les performances du système.
2. Cache du pool de threads de connexion à la base de données
Si chaque demande d'opération de base de données doit créer et détruire une connexion, cela représentera sans aucun doute une énorme surcharge pour la base de données. Afin de réduire ce type de surcharge, thread_cache_size peut être configuré dans MySQL pour indiquer combien de threads sont réservés pour la réutilisation. Lorsqu’il n’y a pas assez de threads, ils sont recréés et lorsqu’il y a trop de threads inactifs, ils sont détruits.
En fait, il existe une approche plus radicale, utilisant pconnect (connexion longue à la base de données), une fois le thread créé, il sera maintenu longtemps. Cependant, lorsque le nombre d'accès est relativement important et qu'il y a de nombreuses machines, cette utilisation est susceptible de conduire à "l'épuisement du nombre de connexions à la base de données", car les connexions ne sont pas recyclées, et finalement le max_connections (nombre maximum de connexions) de la base de données sont atteints. Par conséquent, l'utilisation de connexions longues nécessite généralement la mise en œuvre d'un service de « pool de connexions » entre CGI et MySQL pour contrôler le nombre de connexions créées « à l'aveugle » par la machine CGI.
3. Paramètres du cache Innodb (innodb_buffer_pool_size)
innodb_buffer_pool_size Il s'agit d'une zone de cache mémoire utilisée pour sauvegarder les index et les données. Si la machine est exclusive à MySQL, il est généralement recommandé d'en avoir 80. la mémoire physique de la machine. Dans le scénario de récupération des données de table, cela peut réduire les E/S disque. De manière générale, plus cette valeur est élevée, plus le taux de réussite du cache sera élevé.
4. Sous-bibliothèque/table/partition.
Les tables de base de données MySQL supportent généralement un volume de données de plusieurs millions. S'il augmente encore, les performances chuteront considérablement. Par conséquent, lorsque nous prévoyons que le volume de données dépassera ce niveau, il est recommandé d'effectuer des opérations telles que des sous-données. -base de données/table/partition. La meilleure approche consiste à concevoir le service dans un modèle de stockage de sous-bases de données et de sous-tables dès le début, afin d'éliminer fondamentalement les risques aux étapes intermédiaires et ultérieures. Cependant, certaines commodités, telles que les requêtes basées sur des listes, seront sacrifiées et, dans le même temps, la complexité de la maintenance sera accrue. Cependant, lorsque la quantité de données atteint des dizaines de millions ou plus, nous constaterons qu’elles en valent toutes la peine.
2. Configuration de plusieurs services de base de données MySQL
Une machine MySQL est en fait un point unique à haut risque, car si elle raccroche, notre service Web sera non. plus disponible. De plus, alors que le nombre de visites sur le système Web continuait d'augmenter, un jour, nous avons découvert qu'un serveur MySQL ne pouvait pas le prendre en charge et nous avons commencé à avoir besoin d'utiliser davantage de machines MySQL. Lorsque plusieurs machines MySQL sont introduites, de nombreux nouveaux problèmes surgissent.
1. Établissez un maître-esclave MySQL, avec la base de données esclave comme sauvegarde
Cette approche vise uniquement à résoudre le problème du « point de défaillance unique ». la base de données esclave. Cependant, cette approche constitue en réalité un gaspillage de ressources, car la bibliothèque esclave est en réalité inactive.
2. MySQL sépare la lecture et l'écriture, l'écriture dans la base de données principale et la lecture à partir de la base de données esclave.
Les deux bases de données séparent la lecture et l'écriture. La base de données principale est responsable de l'écriture des classes et la base de données esclave est responsable des opérations de lecture. De plus, si la base de données principale tombe en panne, l'opération de lecture ne sera pas affectée. Dans le même temps, toutes les lectures et écritures peuvent être temporairement basculées vers la base de données esclave (vous devez faire attention au trafic, car celui-ci peut être trop important). et la base de données esclave sera supprimée).
3. Le maître et le maître subviennent mutuellement.
Les deux serveurs MySQL sont à la fois la base de données esclave et la base de données maître l'un de l'autre. Cette solution permet non seulement de détourner la pression du trafic, mais résout également le problème du « point de défaillance unique ». Si une unité tombe en panne, un autre ensemble de services est disponible.
Cependant, cette solution ne peut être utilisée que dans un scénario avec deux machines. Si l'entreprise continue de se développer rapidement, vous pouvez choisir de la séparer et d'établir plusieurs services maître-maître et de sauvegarde mutuelle.
3. Établir un cache entre le serveur web et la base de données
En fait, pour résoudre le problème des visites volumineuses, on ne peut pas simplement se concentrer sur le niveau de la base de données. Selon la « règle des 80/20 », 80 % des requêtes ne portent que sur 20 % des données chaudes. Par conséquent, nous devons établir un mécanisme de mise en cache entre le serveur Web et la base de données. Ce mécanisme peut utiliser le disque comme cache ou cache mémoire. Grâce à eux, la plupart des requêtes de données chaudes sont bloquées devant la base de données.
1. Statique de la page
Lorsqu'un utilisateur visite une certaine page du site Web, la plupart du contenu de la page peut ne pas changer pendant une longue période. Par exemple, une fois qu’un reportage est publié, le contenu ne sera presque jamais modifié. Dans ce cas, la page html statique générée par CGI est mise en cache localement sur le disque du serveur web. Sauf pour la première fois, qui est obtenue via une base de données de requêtes CGI dynamique, le fichier du disque local est ensuite directement renvoyé à l'utilisateur.
Lorsque l'échelle du système Web était relativement petite, cette approche semblait parfaite. Cependant, une fois que l'échelle du système Web devient plus grande, par exemple lorsque j'ai 100 serveurs Web. De cette façon, il y aura 100 copies de ces fichiers disque, ce qui constitue un gaspillage de ressources et difficile à maintenir. À l'heure actuelle, certaines personnes peuvent penser qu'elles peuvent centraliser un serveur pour le stocker. Haha, pourquoi ne pas jeter un œil à la méthode de mise en cache suivante, qui explique comment elle procède.
2. Cache mémoire unique
Grâce à l'exemple de la statique de page, on peut savoir qu'il est difficile de maintenir le "cache" sur la machine web elle-même, et cela apportera plus de problème ( en fait, grâce à l'extension apc de PHP, la mémoire native du serveur web peut être manipulée via Key/value). Par conséquent, le service de cache mémoire que nous choisissons de créer doit également être un service indépendant.
Les principaux choix pour le cache mémoire sont redis/memcache. En termes de performances, il n'y a pas beaucoup de différence entre les deux. En termes de richesse en fonctionnalités, Redis est supérieur.
3. Cluster de cache mémoire
Lorsque nous construisons un seul cache mémoire, nous serons confrontés au problème du point de défaillance unique, nous devons donc le transformer en cluster. Le moyen le plus simple consiste à ajouter un esclave comme machine de sauvegarde. Cependant, que se passe-t-il s'il y a vraiment beaucoup de requêtes et que nous constatons que le taux de réussite du cache n'est pas élevé et que davantage de mémoire machine est nécessaire ? Nous vous recommandons donc de le configurer en cluster. Par exemple, similaire au cluster Redis.
Redis dans le cluster Redis est constitué de plusieurs ensembles de maîtres et d'esclaves en même temps, chaque nœud peut accepter des requêtes, ce qui est plus pratique lors de l'extension du cluster. Le client peut envoyer une requête à n'importe quel nœud, et si c'est le contenu dont il est « responsable », le contenu sera renvoyé directement. Sinon, recherchez le nœud Redis réellement responsable, puis informez le client de l'adresse et le client demande à nouveau.
Tout cela est transparent pour les clients utilisant le service de mise en cache.
Il existe certains risques lors du changement de service de cache mémoire. Lors du passage du cluster A au cluster B, il est nécessaire de s'assurer que le cluster B est "réchauffé" à l'avance (les données chaudes dans la mémoire du cluster B doivent être autant que possible les mêmes que celles du cluster A). , sinon, un grand nombre de requêtes de contenu seront demandées au moment du basculement. Elles ne peuvent pas être trouvées dans le cache mémoire du cluster B. Le trafic impacte directement le service de base de données back-end, ce qui est susceptible de provoquer un temps d'arrêt de la base de données).
4. Réduire les "écritures" de la base de données
Les mécanismes ci-dessus réduisent tous les opérations de "lecture" de la base de données, mais l'opération d'écriture est également une grande pression. Bien que l'opération d'écriture ne puisse pas être réduite, elle peut réduire la pression en fusionnant les requêtes. À ce stade, nous devons établir un mécanisme de synchronisation des modifications entre le cluster de cache mémoire et le cluster de base de données.
Mettez d'abord en vigueur la demande de modification dans le cache, afin que les requêtes externes puissent s'afficher normalement, puis mettez ces modifications SQL dans une file d'attente et stockez-les lorsque la file d'attente est pleine ou de temps en temps, ils seront fusionnés en une seule demande et envoyés à la base de données. Mettez à jour la base de données.
En plus d'améliorer les performances d'écriture en modifiant l'architecture système mentionnée ci-dessus, MySQL lui-même peut également ajuster la stratégie d'écriture sur le disque en configurant le paramètre innodb_flush_log_at_trx_commit. Si le coût de la machine le permet, pour résoudre le problème au niveau matériel, vous pouvez choisir l'ancien RAID (Redundant Arrays of Independent Disks, disk array) ou le plus récent SSD (Solid State Drives, Solid State Drives).
5. Stockage NoSQL
Indépendamment de la lecture ou de l'écriture de la base de données, lorsque le trafic augmente encore, il finira par atteindre le scénario « lorsque la main-d'œuvre est limitée ». Le coût de l’ajout de machines supplémentaires est relativement élevé et ne résoudra peut-être pas vraiment le problème. À l'heure actuelle, vous pouvez envisager d'utiliser la base de données NoSQL pour certaines données de base. La plupart des stockages NoSQL utilisent la méthode clé-valeur. Il est recommandé d'utiliser Redis comme introduit ci-dessus. Redis lui-même est un cache mémoire et peut également être utilisé comme stockage, lui permettant de stocker directement des données sur le disque.
Dans ce cas, nous séparerons certaines données fréquemment lues et écrites dans la base de données et les placerons dans notre nouveau cluster de stockage Redis, ce qui réduira encore davantage la pression sur la base de données MySQL d'origine, car Redis lui-même. est un cache au niveau de la mémoire, les performances de lecture et d'écriture seront grandement améliorées.
Les sociétés Internet nationales de premier rang utilisent de nombreuses solutions similaires aux solutions ci-dessus en termes d'architecture. Cependant, le service de cache utilisé n'est pas nécessairement Redis. Elles auront d'autres options plus riches, et même basées sur. Développer son propre service NoSQL en fonction de ses propres caractéristiques métiers.
6. Problème de requête de nœud vide
Lorsque nous avons construit tous les services mentionnés ci-dessus et pensons que le système Web est déjà très solide. Nous disons toujours la même chose, de nouveaux problèmes surviendront encore. Les requêtes de nœuds vides font référence à des demandes de données qui n'existent pas du tout dans la base de données. Par exemple, si je demande à interroger des informations sur une personne qui n'existent pas, le système recherchera étape par étape dans le cache à tous les niveaux, trouvera finalement la base de données elle-même, puis tirera la conclusion qu'elle est introuvable et retournera à l'avant. Étant donné que les caches à tous les niveaux ne sont pas valides, cette requête consomme beaucoup de ressources système et si un grand nombre de requêtes de nœuds vides sont effectuées, cela peut avoir un impact sur les services système.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!