Cache
Performance
Arquitetura de Software
Backend
Boas Práticas

Cache dans les applications : petit guide des bonnes pratiques (et des erreurs qu'il cache)

Le cache est le moyen le moins coûteux de rendre un système rapide et le moyen le plus subtil de le rendre erroné.

Cache dans les applications : petit guide des bonnes pratiques (et des erreurs qu'il cache)

Le cache est l’un des outils les plus séduisants du génie logiciel. Avec peu d'effort, vous transformez une opération lente en une réponse instantanée. Le système devient plus rapide, l'infrastructure respire, l'utilisateur sourit. Cela ressemble à de la magie.

Et c’est précisément parce que cela semble magique que le cache cause autant de dégâts. Il résout le problème de performances si facilement que les gens répartissent le cache partout, sans se rendre compte qu'ils échangent un problème visible, la lenteur, contre un problème invisible, des données erronées. Et des données erronées sont bien pires que des données lentes.

Ceci est un guide rapide pour bien utiliser le cache. L’idée n’est pas d’épuiser le sujet, mais plutôt de vous donner les critères qui séparent le cache qui aide du cache qui devient piège. Comme le dit la blague informatique classique, il n'y a que deux problèmes difficiles : l'invalidation du cache, la dénomination des éléments et l'erreur un plus un.

À quoi sert le cache, en une phrase

La mise en cache consiste à sauvegarder le résultat d’une opération coûteuse pour le réutiliser, au lieu de refaire l’opération à chaque fois. Vous le calculez une fois, vous l'enregistrez et la prochaine fois, vous fournissez la réponse enregistrée.

L'opération « coûteuse » peut être une requête lourde dans une base de données, un appel à un service externe, un calcul complexe ou le rendu d'une page. Le gain vient du fait de ne pas répéter le travail. Lorsque le même résultat est demandé plusieurs fois et change peu, la mise en cache est presque toujours une bonne idée.

Le mot-clé est « change peu ». C’est là que réside toute la complexité, et c’est là que la plupart des gens se trompent.

Bonne pratique : mettre en cache ce qui est beaucoup lu et change peu

Le candidat de cache idéal présente deux caractéristiques : il est fréquemment consulté et change rarement. Pensez à une liste de catégories de produits, à la configuration d'un système, au profil public d'un utilisateur. Ce type de données est lu en permanence et mis à jour de temps en temps, un cache parfait.

Le mauvais candidat au cache est à l’opposé : des données qui changent à chaque instant ou dont la précision est critique en temps réel. Le solde d'un compte bancaire, le stock disponible au moment de l'achat, le prix en négociation active, la mise en cache peuvent donner à l'utilisateur un chiffre qui n'est plus vrai, avec des conséquences réelles.

La question pratique avant de mettre quoi que ce soit en cache : que se passe-t-il si l'utilisateur voit une valeur obsolète de quelques secondes ou minutes ? Si la réponse est « ce n’est pas grave », mettez en cache. Si la réponse est « un problème sérieux », réfléchissez-y à deux fois.

Le vrai problème : l'invalidation

Mettre des données dans le cache est trivial. La partie difficile est de savoir quand supprimer ou mettre à jour. C’est le problème de l’invalidation, et c’est de là que naissent presque tous les bugs de cache.

Il existe deux stratégies de base, et les deux ont leur place. Le premier est l’expiration du temps : les données restent dans le cache pendant une période définie et sont ensuite supprimées. Simple, robuste et suffisant pour la plupart des cas. Vous acceptez que les données puissent être obsolètes pendant, disons, cinq minutes, et continuez votre vie.

La seconde est l'invalidation d'événement : lorsque les données changent, vous supprimez ou mettez à jour activement la version mise en cache. C'est plus précis, mais plus fragile, cela nécessite que chaque changement de données se souvienne d'en informer le cache, et il suffit d'un chemin oublié pour que l'utilisateur puisse voir indéfiniment les anciennes informations.

Bonne pratique pour un guide rapide : privilégiez l’expiration programmée chaque fois que la tolérance le permet. C'est plus simple, plus résistant à l'erreur humaine et évite la classe de bug où le cache "oublie" de se mettre à jour. Réservez l’invalidation des événements lorsque la précision justifie vraiment la complexité.

Bonne pratique : définir ce qui se passe lorsque le cache échoue

Le cache est une couche supplémentaire et les couches supplémentaires échouent. Le serveur de cache peut tomber en panne, devenir indisponible ou ralentir. La question à laquelle beaucoup de gens oublient de répondre : qu’est-ce que le système arrête alors ?

Une mise en cache bien faite est une optimisation, pas une dépendance. Si le cache disparaît, l'application doit continuer à fonctionner, peut-être plus lentement, mais en travaillant, en recherchant les données de la source d'origine. Lorsque l’ensemble du système plante à cause d’une panne du cache, vous n’avez pas d’optimisation ; a un point de défaillance unique déguisé en amélioration des performances.

Il y a aussi un détail perfide : lorsque le cache se vide d'un coup, toutes les requêtes atteignent la source d'origine en même temps, et la surcharge peut détruire précisément ce que le cache protégeait. C'est un effet connu, et il vaut la peine de concevoir la récupération en gardant cela à l'esprit, afin que le système réchauffe le cache sans se noyer.

Réflexion critique : le cache cache le mauvais problème

Il existe une utilisation du cache qui est à la fois techniquement correcte et stratégiquement paresseuse : le cache pour masquer une requête mal formulée. La requête est lente car elle est mal écrite ou la base de données est mal modélisée, et au lieu de corriger la cause, un cache est lancé dessus. Cela fonctionne, jusqu'à ce que le cache expire, jusqu'à ce que le cas non-cache apparaisse, jusqu'à ce que le problème disparaisse.

Le cache doit accélérer ce qui est déjà efficace, et non compenser ce qui est inefficace. Lorsque vous utilisez le cache pour rendre quelque chose de supportable qui devrait être corrigé, cela vaut la peine de s'arrêter et d'en examiner la cause. Le cache, dans ce cas, reporte une dette, ne la paie pas.

Il y a aussi le coût cognitif. Chaque couche de cache est un élément supplémentaire dans lequel les données peuvent être obsolètes, un endroit supplémentaire pour enquêter lorsque quelque chose est étrange. « Pourquoi cet utilisateur voit-il d'anciennes informations ? » est l'une des questions les plus frustrantes à déboguer, précisément parce que le cache est invisible jusqu'à ce qu'il y ait un problème. Trop de cache transforme un système simple en un casse-tête de gestion des versions. Utilisez avec parcimonie, documentez où vous vous trouvez et préférez moins de couches bien comprises à de nombreuses couches mystérieuses.

Ce qui reste

Le cache est un outil puissant et est également souvent utilisé à mauvais escient. Bien utilisé, il laisse des systèmes rapides et bon marché. Il est utilisé à mauvais escient, fournit des informations erronées, cache de vrais problèmes et crée des bugs difficiles à suivre.

Les bonnes pratiques tiennent en quelques lignes : mettre en cache ce qui est beaucoup lu et change peu ; préférer l’expiration programmée à l’invalidation manuelle ; garantir que le système survit sans le cache ; et n'utilisez jamais la mise en cache pour masquer un problème qui devrait être résolu. Le reste est à peaufiner.

Si vous rencontrez des problèmes de performances et envisagez la mise en cache comme solution, il convient d'abord de comprendre si le goulot d'étranglement provient réellement de lectures répétées ou de quelque chose de plus profond. Sur le blog, vous trouverez d'autres textes sur le backend, les performances et l'architecture qui approfondissent ces choix.

A lire aussi

-Backend pour les applications : bonnes pratiques pour les petites équipes qui ne peuvent pas faire d'erreurs