Maison > Article > base de données > Analysez les problèmes de stockage des touches de raccourci dans Redis et discutez des solutions pour mettre en cache les exceptions
Cet article parlera de trois anomalies de cache courantes dans Redis : la pénétration du cache, la panne du cache et l'avalanche de cache. À travers elles, nous parlerons des problèmes de stockage des touches de raccourci dans Redis. J'espère que cela sera utile à tout le monde !
Recommandations associées : "Analysons ensemble les problèmes de cohérence du cache Redis, de pénétration du cache, de panne de cache et d'avalanche de cache"
La pénétration du cache, la panne de cache et l'avalanche de cache sont des interviews Redis et des faits réels. est une question à laquelle il faut souvent réfléchir. Beaucoup de gens ne savent toujours pas exactement l’origine, la cause et la solution de ce problème. En fait, pour ces trois situations, on peut trouver une bonne solution en analysant soigneusement le principe généré. [Recommandations associées : Tutoriel vidéo Redis]
Cet article vous aide à comprendre rapidement ces trois problèmes à travers des définitions, des cas, des dangers et des solutions.
Je pense que vous avez vu de nombreuses solutions à ces trois problèmes sur Internet. Certaines d'entre elles sont-elles des solutions correctes
? Cet article analysera également un par un les avantages et les inconvénients de telles solutions. 正确的
方案呢?本文也将一一分析此类方案的优缺点。
下图为本文的内容大纲,文章也是围绕这几点进行分析与总结。
缓存穿透、缓存击穿和缓存雪崩都是因为缓存中数据不存在,导致走数据库去查询数据。
由于缓存数据不存在,所有的请求都会走到数据库,因此会导致数据库的压力过大甚至出现服务崩溃,导致整个系统无法使用。
定义:缓存穿透是由于客户端求的数据在缓存中不存在,然后去查询数据库,然而数据库没有客户端要查询的数据,导致每一次请求都会走数据库查询操作。真正的问题在于该数据本身就是不存在的
。
举例:客户端请求商品详情信息时,携带一个商品ID,此时该商品ID是不存在的(不管是缓存中还是数据库中)。导致每一次请求该ID商品的数据信息都会走数据库。
危害:由于请求的参数对应的数据根本不存在,会导致每一次都会请求数据库,增加数据库的压力或者服务崩溃,更有甚至影响到其他的业务模块。经常发生在用户恶意请求
的情况下会发生。
解决方案:
1、根据请求的参数缓存一个null值。并且为该值设置一个过期时间,可以将时间设置短暂一点。
2、使用布隆过滤器,首先通过布隆过滤器进行筛选,如果在过滤器中存在则去查询数据库,然后添加到缓存中。如果不存在则直接返回客户端数据不存在。
3、由于缓存穿透可能是用户发起恶意请求,可以将用户ip给记录下来,针对恶意的ip请求进行封禁。
方案分析:
第一种方案,针对不存在的key,会缓存一个空的值。假设这样的请求特别多,是否都会一一去设置一个空值的缓存,此时Redis中就存在大量无效的缓存空值。假设这样的key是商品或者文章类的ID,我们在设置空值之后,如果后台添加数据应该去更新ID对应的缓存值,并设置一个合理的过期时间。
第二种方案,也是业界使用最多的一种方案。布隆过滤器的优点在于基于Redis实现,内存操作并且底层的实现也是非常节约内存。 当后台添加数据成功时,将该数据的ID添加到布隆过滤器中,前端在请求时先走布隆过滤器进行验证是否存在。但布隆过滤器也存在一个弊端,就是hash冲突问题。这里的hash冲突是什么意思呢?就是说多个ID在进行hash计算时,得到的hash位都是同一个值,这就导致在验证是否存在时误判。本身是有的,得到的结果是没有。布隆过滤器的一个弊端就是,它说有并不一定有,它说没有就一点是没有的。
Comparaison des trois
Comme les données mises en cache n'existent pas, toutes les requêtes iront vers la base de données, ce qui entraînera une pression excessive sur la base de données voire un crash du service, rendant l'ensemble du système inutilisable. 🎜🎜🎜
Le vrai problème est que les données elles-mêmes n'existent pas
. 🎜🎜Exemple : Lorsque le client demande les détails du produit, il porte un identifiant de produit. A ce moment, l'identifiant du produit n'existe pas (ni dans le cache, ni dans la base de données). Par conséquent, chaque fois que les données du produit portant cet identifiant seront demandées, elles seront transférées dans la base de données. 🎜🎜Risques : Les données correspondant aux paramètres demandés n'existant pas du tout, la base de données sera sollicitée à chaque fois, augmentant la pression sur la base de données ou le service crashant, et affectant même d'autres modules métiers. Cela se produit souvent lorsque les utilisateurs font des demandes malveillantes
. 🎜🎜🎜Solution : 🎜🎜🎜1. Mettez en cache une valeur nulle en fonction des paramètres demandés. Et définissez un délai d'expiration pour cette valeur, vous pouvez définir le délai pour qu'il soit plus court. 🎜🎜2. Utilisez le filtre Bloom. Filtrez d'abord via le filtre Bloom. S'il existe dans le filtre, interrogez la base de données puis ajoutez-le au cache. Si elle n'existe pas, il renverra directement que les données client n'existent pas. 🎜🎜3. Étant donné que la pénétration du cache peut être causée par des utilisateurs lançant des requêtes malveillantes, l'adresse IP de l'utilisateur peut être enregistrée et les requêtes IP malveillantes peuvent être bloquées. 🎜🎜🎜 Analyse de la solution : 🎜🎜L'un des inconvénients du filtre Bloom est qu'il n'existe pas nécessairement s'il dit qu'il existe, et cela signifie qu'il n'existe pas s'il n'existe pas.
🎜🎜🎜🎜La troisième option consiste à lancer un grand nombre de requêtes pour le même utilisateur dans un laps de temps donné, déclenchant le mécanisme de pénétration du cache. À ce moment, nous pouvons afficher l'accès du client. Cependant, si l’attaquant lance une attaque DDOS, il ne peut pas complètement éviter de telles attaques, cette solution n’est donc pas une bonne solution. 🎜🎜🎜🎜🎜Résumé du plan : 🎜🎜Nous ajoutons d'abord la troisième solution au niveau des requêtes, créant un mécanisme de limitation de courant et un mécanisme de liste noire IP pour contrôler certaines requêtes malveillantes, en cas d'erreur de jugement, nous pouvons mettre en œuvre des opérations telles que le déblocage IP. La couche cache est implémentée à l'aide de la première solution. Définissez un temps de cache raisonnable.
Pour les scénarios commerciaux pouvant tolérer des erreurs de jugement, vous pouvez directement utiliser la deuxième solution. Entièrement basé sur Redis, réduisant la complexité du système.
Définition : La panne du cache est due au fait qu'une clé de point d'accès n'existe pas, ce qui entraîne une requête de base de données. Pression accrue sur la base de données. Cette pression peut être momentanée ou de plus longue durée. 真正的问题在于该key是存在,只是缓存中不存在,导致走数据库操作
.
Par exemple : il existe un produit populaire. Lorsque les utilisateurs consultent les détails du produit, ils portent l'ID du produit pour obtenir les détails du produit. À ce stade, les données du cache ont expiré, toutes les demandes entrantes doivent donc être adressées à la base de données pour être interrogées.
Dangers : par rapport à la pénétration du cache, les données existent dans la base de données, mais comme le cache a expiré, elles doivent aller dans la base de données une fois, puis elles sont ajoutées au cache, et la requête suivante peut aller au cache normalement. Le soi-disant préjudice concerne également le niveau des bases de données.
Solution :
1. Ajoutez un verrou mutex. Pour la première requête, il a été constaté qu'il n'y avait aucune donnée dans le cache. À ce moment-là, la base de données de requêtes a été ajoutée au cache. De cette façon, les requêtes ultérieures n’ont pas besoin de passer par des requêtes de base de données.
2. Augmentez le délai d'expiration de la logique métier. Lors de la configuration du cache, nous pouvons ajouter un délai d'expiration du cache. Chaque fois que vous lisez, portez un jugement. Si le délai d'expiration est inférieur à l'heure actuelle, déclenchez un thread en arrière-plan, accédez à la base de données pour extraire les données, puis mettez à jour les données mises en cache et le délai d'expiration mis en cache. En fait, le principe est d’allonger la durée du cache au niveau du code.
3. Échauffement des données. Implémentez l'ajout de données au cache en arrière-plan. Par exemple, avant le début de la scène de vente flash, l'inventaire du produit est ajouté au cache, de sorte que lorsque la demande de l'utilisateur arrive, il ira directement dans le cache.
4. N’expire jamais. Lorsque vous définissez un délai d'expiration pour le cache, veillez à ce qu'il n'expire jamais. Un thread distinct est ouvert en arrière-plan pour maintenir le délai d'expiration et les mises à jour des données de ces caches.
Analyse du projet :
Le verrouillage mutex garantit qu'une seule requête est envoyée à la base de données, ce qui est un avantage. Cependant, pour les systèmes distribués, les verrous distribués sont utilisés pour mettre en œuvre des verrous distribués. La mise en œuvre des verrous distribués elle-même présente certaines difficultés, ce qui augmente la complexité du système.
La deuxième solution est mise en œuvre en utilisant Redis pour éviter l'expiration et l'expiration de l'entreprise. Cela garantit que chaque requête peut obtenir les données et, en même temps, un thread d'arrière-plan peut être utilisé pour mettre à jour les données. L'inconvénient est que le thread d'arrière-plan n'a pas fini de mettre à jour les données. Pour le moment, les données demandées sont des données anciennes, ce qui peut présenter des inconvénients dans les scénarios commerciaux avec des exigences élevées en temps réel.
La troisième solution consiste à utiliser le préchauffage du cache et le cache à chaque chargement, ce qui est similaire à la deuxième solution. Cependant, il existe également le problème de la mise à jour des données à chaud, cette solution convient donc aux données qui ne nécessitent pas de données en temps réel élevées.
La quatrième solution est similaire aux deuxième et troisième solutions. Sur cette base, certaines optimisations ont été apportées, en utilisant des threads asynchrones en arrière-plan pour mettre à jour activement les données mises en cache. La difficulté réside dans le contrôle de la fréquence des mises à jour.
Résumé de la solution :
Pour les données avec des exigences élevées en temps réel, il est recommandé d'utiliser la première solution Bien qu'elle soit techniquement difficile, elle permet de réaliser un traitement des données en temps réel. Si certaines requêtes attendent longtemps, une exception peut être renvoyée et le client peut renvoyer la requête.
Pour les données qui ne nécessitent pas de performances élevées en temps réel, vous pouvez utiliser la quatrième option.
Définition : Comme mentionné précédemment, la panne du cache est due au fait qu'une certaine touche de raccourci dans le cache échoue, provoquant l'accès d'un grand nombre de requêtes à la base de données. Cependant, l'avalanche de cache est en réalité la même, mais celle-ci est plus grave. La plupart des clés mises en cache sont invalides, plutôt qu'une ou deux clés.
Exemple : Dans un système de commerce électronique, les données produit d'une certaine catégorie ne sont pas valides dans le cache. Cependant, de nombreuses demandes du système actuel concernent des données de produits relevant de cette catégorie. Cela fait que toutes les demandes passent par des requêtes de base de données.
Risques : En raison de l'afflux d'un grand nombre de demandes en un instant, chaque demande doit être interrogée dans la base de données. L'afflux instantané de trafic vers la base de données augmente considérablement la charge qui pèse sur la base de données et peut facilement conduire à une paralysie directe de la base de données.
Solution :
1. Le temps de cache est aléatoire. Étant donné qu'un grand nombre de caches expirent à un certain moment, cela signifie que le délai d'expiration du cache est relativement concentré. Nous définissons directement le délai d'expiration pour qu'il soit flou et aléatoire. De cette façon, le temps d'expiration du cache ne sera pas très concentré et il n'y aura pas un grand nombre de requêtes adressées à la base de données pour des opérations de requête en même temps.
2. Cache multi-niveaux. Au lieu de simplement compter sur Redis pour la mise en cache, nous pouvons également utiliser memcached pour la mise en cache (voici juste un exemple, d'autres services de mise en cache peuvent également être utilisés). Lors de la mise en cache des données, créez un cache pour Redis et un cache pour memcached. Si Redis échoue, nous pouvons utiliser Memcached.
3. Verrouillage Mutex. Dans la panne de cache, nous avons évoqué l'utilisation de verrous mutex, et nous pouvons également l'utiliser en cas d'avalanche.
4. Définir le drapeau d'expiration. En fait, vous pouvez également utiliser la non-expiration permanente mentionnée dans la panne du cache. Lors de la demande, le délai d'expiration est déterminé. Si le délai d'expiration approche, un indicateur d'expiration est défini et un thread indépendant est déclenché pour mettre à jour le cache.
Analyse de la solution :
La première solution utilise un temps de mise en cache de nombres aléatoires pour garantir que le délai d'expiration de la clé est dispersé. La difficulté réside dans la manière de définir le temps de cache. Pour certaines données nécessitant un temps de cache court et une très grande quantité de données, cette solution nécessite un contrôle raisonnable du temps.
La deuxième solution utilise un cache à plusieurs niveaux, qui peut garantir que toutes les demandes sont mises en cache. Cependant, cela augmente la difficulté architecturale du système et divers autres problèmes, tels que la mise en cache des mises à jour multi-niveaux.
La troisième solution utilise des verrous mutex. Nous avons mentionné les verrous mutex dans la panne de cache. Bien que nous puissions les utiliser dans des scénarios d'avalanche, cela générera un grand nombre de verrous distribués.
La quatrième solution utilise le temps de cache logique, ce qui garantit bien la pression du cache du système.
Résumé du plan :
Dans les projets réels, il est recommandé d'utiliser le 1er, le 2ème et le 4ème plan pour l'essayer, qui sera meilleur.
La pénétration du cache est due au fait que la base de données elle-même ne contient pas les données.
Une panne de cache et une avalanche de cache signifient que les données existent dans la base de données, mais que les données dans le cache ne sont pas valides, ce qui entraîne une nouvelle interrogation de la base de données, puis son ajout au cache.
La panne du cache concerne certaines touches de raccourci, tandis que l'avalanche de cache est une panne de cache à grande échelle. Les deux principes sont en réalité les mêmes, sauf que la répartition des clés de cache est différente.
Pour plus de connaissances liées à la programmation, veuillez visiter : Introduction à la programmation ! !
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!