1. Introduction
Redis (Remote Dictionary Server), le service de dictionnaire distant, est un open source écrit en langage ANSI C, prend en charge le réseau et peut être basé sur la mémoire ou la mémoire. Une base de données durable de type journal, clé-valeur, et fournit des API dans plusieurs langues.
(Partage vidéo d'apprentissage : tutoriel vidéo Redis)
Parce qu'il est rapide à démarrer, a une efficacité d'exécution élevée, possède une variété de structures de données, prend en charge la persistance et le clustering et d'autres fonctions et fonctionnalités sont utilisés par de nombreuses sociétés Internet. Cependant, s’il est utilisé et utilisé de manière incorrecte, il entraînera de graves conséquences telles qu’un gaspillage de mémoire et même un temps d’arrêt du système.
2. Analyse des points clés
2.1 Utiliser le bon type de données
Parmi les 5 types de données dans Redis, le type chaîne est le plus couramment utilisé et le plus simple. Cependant, être capable de résoudre un problème ne signifie pas que vous utilisez le bon type de données.
Par exemple, pour enregistrer les informations d'un utilisateur (nom, âge, ville) dans Redis, il existe trois options ci-dessous :
Option 1 : utiliser le type de chaîne, chaque attribut est traité comme une clé
set user:1:name laowang set user:1:age 40 set user:1:city shanghai
Avantages : simple et intuitif, chaque attribut prend en charge les opérations de mise à jour
Inconvénients : utilisation de trop de clés, occupation d'une grande quantité de mémoire et mauvaise agrégation des informations utilisateur, rendant la gestion et la maintenance fastidieuses
Option 2 : utilisez le type chaîne pour sérialiser les informations utilisateur dans une chaîne et enregistrez-les
// 序列化用户信息 String userInfo = serialize(user) set user:1 userInfo
Avantages : étapes de stockage simplifiées
Inconvénients : il y a une certaine surcharge dans la sérialisation et la désérialisation
Option 3 : Utiliser le type de hachage, utiliser une paire champ-valeur pour chaque attribut, mais n'utiliser qu'une seule clé
hmset user:1 name laowang age 40 city shanghai
Avantages : simple et intuitif, une utilisation raisonnable peut réduire l'espace mémoire
Résumé : Réduisez autant que possible les clés dans Redis.
2.2 Méfiez-vous des grosses clés
Les grosses clés font généralement référence à une valeur de type chaîne avec une très grande valeur (supérieure à 10 Ko), ou à un hachage, une liste, un ensemble ou un ensemble ordonné avec un grand nombre d'éléments (supérieur à 5000) clés.
Une grosse clé aura de nombreux impacts négatifs sur Redis :
Mémoire inégale : dans un environnement de cluster, une grosse clé est allouée à une certaine machine de nœud, car on ne sait pas à quel nœud elle est allouée to. et le nœud occupe une grande mémoire, ce qui n'est pas propice à la gestion unifiée de la mémoire dans un environnement de cluster
Blocage du délai d'attente : étant donné que Redis est une opération monothread, l'exploitation de grosses clés prend du temps et peut facilement provoquer un blocage
Suppression après expiration : les grosses clés sont non seulement lentes à lire et à écrire, mais également lentes à supprimer. La suppression des grosses clés expirées prend également du temps
Difficulté de migration : due. aux données énormes, la sauvegarde et la restauration peuvent facilement provoquer une congestion et un échec de fonctionnement
Connaissant les dangers des grosses clés, comment pouvons-nous juger et interroger les grosses clés ? En fait, redis-cli fournit le paramètre --bigkeys Tapez redis-cli --bigkeys pour interroger la grande clé.
Après avoir trouvé la grande clé, nous divisons généralement la grande clé en plusieurs petites clés pour le stockage. Cette approche semble contredire le résumé du point 2.1, mais toute solution présente des avantages et des inconvénients, et la pesée du pour et du contre dépend de la situation réelle.
Résumé : Essayez de réduire les grosses clés dans Redis.
Supplémentaire : Si vous souhaitez vérifier l'espace mémoire occupé par une certaine clé, vous pouvez utiliser la commande d'utilisation de la mémoire. Remarque : Cette commande est uniquement disponible dans Redis 4.0+. Si vous souhaitez l'utiliser, vous devez mettre à niveau Redis vers 4.0+.
2.3 Consommation de mémoire
Même si nous utilisons le bon type de données pour enregistrer les données et diviser la Big Key en petites clés, des problèmes de consommation de mémoire se produiront toujours. Alors, comment se produit la consommation de mémoire Redis ? ? Généralement causé par les trois situations suivantes :
Les affaires continuent de se développer et la quantité de données stockées continue d'augmenter (inévitable)
Les données invalides/expirées ne sont pas traitées en temps opportun (peut être optimisé)
Les données froides ne sont pas déclassées (peuvent être optimisées)
Avant d'optimiser le cas 2, il faut d'abord savoir pourquoi il y a un problème de non-traitement des données expirées dans les délais Cela concerne les 3 types fournis par Redis Stratégie de suppression après expiration :
Suppression planifiée : un minuteur sera créé pour chaque clé avec un délai d'expiration défini, et il sera supprimé immédiatement une fois l'expiration terminée. le temps est atteint
Suppression paresseuse : lors de l'accès à une clé, déterminez si la clé a expiré, supprimez-la
Suppression régulière : analysez le dictionnaire des clés expirées dans Redis à. intervalles réguliers et effacer certaines clés expirées
En raison du timing, la suppression nécessite la création d'une minuterie, qui occupera beaucoup de mémoire. En même temps, la suppression précise d'un grand nombre de clés consommera également. beaucoup de ressources CPU. Par conséquent, Redis utilise à la fois des stratégies de suppression différée et de suppression planifiée. Si le client ne demande pas de clé expirée ou si le thread de suppression régulier n'analyse et n'efface pas la clé, la clé continuera à occuper la mémoire, ce qui entraînera un gaspillage de mémoire.
Après avoir connu la cause de la consommation de mémoire, nous pouvons rapidement proposer une solution d'optimisation : la suppression manuelle.
Après avoir utilisé le cache, même si le cache a un délai d'expiration défini, nous devons appeler manuellement la méthode/commande del pour le supprimer. S'il ne peut pas être supprimé sur place, nous pouvons également démarrer un minuteur dans le code pour supprimer régulièrement ces clés expirées. Par rapport aux deux stratégies de suppression de Redis, la suppression manuelle des données est beaucoup plus rapide.
Le problème dans le cas 3 n'est pas grave. Pour son optimisation, nous pouvons ajuster la stratégie d'élimination de Redis.
2.4 Exécution de plusieurs commandes
Redis est un service de requête synchrone basé sur une requête et une réponse. Autrement dit, lorsque plusieurs clients envoient des commandes au serveur Redis, le serveur Redis ne peut recevoir et traiter que la commande de l'un des clients. Les autres clients ne peuvent qu'attendre que le serveur Redis traite la commande en cours et réponde avant de continuer la réception. et traiter d'autres demandes de commande.
Redis traite les commandes en trois processus : réception des commandes, traitement des commandes et renvoi des résultats. Étant donné que les données traitées sont toutes en mémoire, le temps de traitement est généralement de l'ordre de la nanoseconde, ce qui est très rapide (sauf pour les grosses touches). Par conséquent, la plupart des situations chronophages se produisent lors de l’acceptation de commandes et du renvoi des résultats. Lorsque le client envoie plusieurs commandes au serveur Redis, si une commande prend beaucoup de temps à traiter, les autres commandes ne peuvent qu'attendre, affectant ainsi les performances globales.
Afin de résoudre ce type de problème, Redis fournit un pipeline. Le client peut mettre plusieurs commandes dans le pipeline, puis envoyer les commandes du pipeline au serveur Redis pour traitement en même temps. Lors du traitement, les résultats sont renvoyés au client en une seule fois. Ce traitement réduit le nombre d'interactions entre le client et le serveur Redis, réduisant ainsi le temps d'aller-retour et améliorant les performances.
Supplément :
Comparaison entre le pipeline Redis et les commandes batch natives :
Les commandes batch natives sont atomiques, le pipeline est non atomique
Les commandes batch natives sont disponible une seule fois Peut exécuter une commande et le pipeline prend en charge l'exécution de plusieurs commandes
Les commandes par lots natives sont implémentées côté serveur. Pipeline nécessite des implémentations serveur et client
Remarques sur l'utilisation du pipeline Redis. :
Le nombre de commandes chargées à l'aide du pipeline ne peut pas être trop grand
Les commandes du pipeline seront exécutées dans l'ordre tamponné, mais elles peuvent être entrecoupées de commandes envoyées par d'autres clients, cela c'est-à-dire que le timing n'est pas garanti
Si une exception se produit lors de l'exécution d'une instruction dans le pipeline, les instructions suivantes continueront d'être exécutées, c'est-à-dire que l'atomicité n'est pas garantie
2.5 Pénétration du cache
Utiliser le cache dans le projet, notre idée de conception habituelle est la suivante :
Envoyer une requête pour interroger des données. vérifiez d'abord le cache. S'il n'y a pas de données dans le cache, interrogez à nouveau la base de données, placez les données trouvées dans la base de données et renvoyez enfin les données au client. Si les données demandées n'existent pas, chaque requête sera finalement demandée à la base de données, ce qui constitue une pénétration du cache.
La pénétration du cache pose un risque de sécurité énorme. Si quelqu'un utilise un outil pour envoyer un grand nombre de requêtes pour des données inexistantes, un grand nombre de requêtes afflueront dans la base de données, provoquant une pression accrue sur la base de données et provoquer éventuellement l'échec de la base de données. Les temps d'arrêt affecteront le fonctionnement normal de l'ensemble de l'application et entraîneront une paralysie du système.
Pour résoudre ce type de problème, l'accent est mis sur la réduction de l'accès à la base de données. Il existe généralement les solutions suivantes :
Échauffement du cache : une fois le système libéré et mis en ligne, les données pertinentes sont directement chargées dans le cache à l'avance.
Définissez la valeur par défaut dans le système : si la requête aboutit dans la base de données et que la base de données ne trouve pas les données, définissez une valeur par défaut pour la clé de cache et mettez-le dans le cache. Remarque : Puisque cette valeur par défaut n'a aucun sens, nous devons donc définir le délai d'expiration pour réduire l'utilisation de la mémoire.
Filtre Bloom : hachez toutes les données possibles dans un bitmap suffisamment grand et inexistant. les données seront définitivement interceptées par le bitmap
2.6 Avalanche de cache
Avalanche de cache : en termes simples, elle fait référence à un grand nombre de requêtes pour accéder aux données mises en cache mais ne peut pas être interrogée, et demande ensuite la base de données, ce qui entraîne une pression accrue sur la base de données, une dégradation des performances et des temps d'arrêt de charge insupportables, affectant ainsi le fonctionnement normal de l'ensemble du système, voire une paralysie du système.
Par exemple, un système complet se compose de trois sous-systèmes : Système A, Système B et Système C. Leur chaîne de demande de données est Système A -> Système B -> Système C -> Base de données. S'il n'y a aucune donnée dans le cache et que la base de données est en panne, le système C ne peut pas interroger les données et répondre et ne peut être qu'en phase d'attente de nouvelle tentative, affectant ainsi le système B et le système A. Une anomalie dans un nœud provoque une série de problèmes, tout comme une rafale de vent soufflant sur une montagne enneigée provoquant une avalanche.
En voyant cela, certains lecteurs se demandent peut-être quelle est la différence entre la pénétration du cache et l'avalanche de cache ?
La pénétration du cache se concentre sur le fait que les données demandées ne sont pas dans le cache, donc demander la base de données revient à demander la base de données directement via le cache.
L'avalanche de cache se concentre sur les requêtes volumineuses Étant donné que les données ne peuvent pas être interrogées dans le cache, l'accès à la base de données augmentera la pression sur la base de données et provoquera une série d'exceptions.
Pour résoudre le problème d'avalanche de cache, vous devez d'abord connaître la cause du problème :
Redis lui-même a un problème
L'ensemble de données de point d'accès échoue
Pour la raison 1, nous pouvons utiliser le maître-esclave et le clustering pour essayer de faire en sorte que toutes les requêtes trouvent des données dans le cache et réduisent l'accès à la base de données
Pour la raison 2, lors de la définition de l'expiration Pour le cache, échelonnez le délai d'expiration (par exemple, en ajoutant ou en soustrayant une valeur aléatoire à l'heure de base) pour éviter une défaillance du cache centralisé. Parallèlement, on peut également mettre en place un cache local (comme ehcache) pour limiter le débit de l'interface ou rétrograder le service, ce qui peut également réduire la pression d'accès sur la base de données.
3. Documents de référence
Opérations de pipeline dans Redis
Application Redis - Filtre Bloom
Recommandations associées : Tutoriel de base de données Redis
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!