How to choose between cache-aside, read-through, write-through, client-side, and distributed caching strategies Comme nous l’avons mentionné dans le récent post, nous sommes ravis que Pekka Enberg ait décidé d'écrire Et nous sommes fiers de soutenir 3 chapitres de celui-ci. Pourquoi cacher les données ? Un livre sur la latence Obtenez l'extrait du livre Latency PDF Obtenez l'extrait du livre Latency PDF Obtenez l'extrait du livre Latency PDF En outre, Pekka vient de partager des prises de vue clés de ce livre dans un (Actuellement disponible sur demande) Masterclass sur la construction d'applications à faible latence Continuons notre extraits du livre avec plus du chapitre de cache de Pekka. Il est réimprimé ici avec l'autorisation de l'éditeur. Latence *** à Lors de l’ajout de la mise en cache à votre application, vous devez d’abord considérer votre stratégie de mise en cache, qui détermine comment les lectures et écritures se produisent à partir de la mise en cache et du stockage de sauvegarde sous-jacent, tels qu’une base de données ou un service. À un niveau élevé, vous devez décider si le cache est passif ou actif lorsqu'il y a un manque de cache.En d'autres termes, lorsque votre application regarde une valeur du cache, mais que la valeur n'est pas là ou a expiré, la stratégie de cache commande si c'est votre application ou le cache qui récupère la valeur du magasin de sauvegarde.Comme d'habitude, les différentes stratégies de cache ont des compromis différents sur la latence et la complexité, alors passons-y. Le cache-aside Lorsqu'il y a un cache hit, la latence d'accès aux données est dominée par la latence de communication, qui est généralement petite, car vous pouvez obtenir un cache à proximité sur un serveur cache ou même dans votre espace de mémoire d'application. Cependant, lorsqu'il y a un cache miss, avec cache-side caching, le cache est un magasin passif mis à jour par l'application. C'est-à-dire, le cache ne fait que signaler un miss et l'application est responsable de la collecte des données du magasin de sauvegarde et de la mise à jour du cache. La figure 1 montre un exemple de cache-side caching en action. Une application regarde une valeur d'un cache par une clé de cache, ce qui détermine les données qui intéressent l'application. Si la clé existe dans le cache, le cache renvoie la valeur associée à la clé, que l'application peut utiliser. Cependant, si la clé n'existe pas ou est expirée dans le cache, nous avons un manque de cache, que l'application doit gérer. Supposons que vous cachez les informations de l'utilisateur et que vous utilisiez l'ID de l'utilisateur comme clé de recherche. Dans ce cas, l'application exécute une requête par l'ID de l'utilisateur pour lire les informations de l'utilisateur de la base de données. Les informations de l'utilisateur retournées de la base de données sont ensuite transformées en un format que vous pouvez stocker dans le cache. Ensuite, le cache est mis à jour avec l'ID de l'utilisateur en tant que clé de cache et les informations en tant que valeur. Par exemple, une façon typique d'effectuer ce type de caching est de transformer les informations de l'utilisateur retournées de la base de données en JSON et de stocker ceci dans le cache. Le cache-side caching est populaire car il est facile de configurer un serveur cache comme Redis et de l'utiliser pour cacher les requêtes de base de données et les réponses aux services. Avec le cache-side caching, le serveur cache est passif et n'a pas besoin de savoir quelle base de données vous utilisez ou comment les résultats sont cartographiés dans le cache. Dans de nombreux cas, le cache-side caching est un moyen simple et efficace de réduire la latence de l'application. Vous pouvez cacher la latence d'accès à la base de données en ayant les informations les plus pertinentes dans un serveur de cache proche de votre application. Par exemple, si vous avez plusieurs lecteurs simultanés qui recherchent une clé dans le cache, vous devez coordonner dans votre application la façon dont vous traitez les manquements de cache simultanés ; sinon, vous pourriez finir par avoir plusieurs accès à des bases de données et des mises à jour de cache, ce qui peut entraîner des recherches de cache ultérieures renvoyant des valeurs différentes. Cependant, avec le cache-side caching, vous perdez le support de la transaction parce que le cache et la base de données ne se connaissent pas les uns les autres, et il est de la responsabilité de l'application de coordonner les mises à jour des données. Enfin, le cache-side caching peut avoir une latence de queue importante parce que certaines recherches de cache expérimentent la latence de lecture de la base de données lors d'une absence de cache. C'est-à-dire, bien que dans le cas d'un cache hit, la latence d'accès est rapide parce qu'elle provient d'un serveur de cache proche; les recherches de cache qui expérimentent une absence de cache sont seulement aussi rapides que l'accès à la base de données. Lire à travers le caching Le caching par lecture est une stratégie dans laquelle, contrairement au caching à côté du cache, le cache est un composant actif lorsqu'il y a un manque de cache. Lorsqu'il y a un manque de cache, un cache par lecture tente de lire automatiquement une valeur pour la clé du backing store. La latence est similaire au caching à côté du cache, bien que la latence de récupération du backing store soit du cache au backing store, pas de l'application au backing store, qui peut être plus petite, selon votre architecture de déploiement. La figure 2 montre un exemple d'un cache de lecture en action. L'application effectue une recherche de cache sur une clé, et s'il y a une cache manquante, le cache effectue une lecture à la base de données pour obtenir la valeur pour la clé. Le cache s'actualise ensuite et renvoie la valeur à l'application. Du point de vue de l'application, une cache manquante est transparente car le cache renvoie toujours une clé si elle existe, indépendamment du fait qu'il y ait une cache manquante ou non. Le caching par lecture est plus complexe à mettre en œuvre car un cache doit pouvoir lire le stockage de sauvegarde, mais il doit également transformer les résultats de la base de données en un format pour le cache. Par exemple, si le stockage de sauvegarde est un serveur de base de données SQL, vous devez convertir les résultats de la requête en un format JSON ou similaire pour stocker les résultats dans le cache. Cependant, parce que le cache coordonne les mises à jour et que la base de données se lit avec le cache de lecture, il peut donner des garanties transactionnelles à l'application et assurer la cohérence sur les manquements de cache concomitants. Bien sûr, la même mise en garde de la latence de la queue s’applique aux caches de lecture comme elles le font pour le cache-side. Une exception: en tant que composants actifs, les caches de lecture peuvent mieux cacher la latence avec, par exemple, le cache de mise à jour. Ici, le cache met asynchroniquement à jour le cache avant l’expiration des valeurs – c’est pourquoi il cache la latence d’accès de la base de données des applications quand une valeur est dans le cache. Écrire à travers le caching Dans de tels cas, le cache fournit une interface pour mettre à jour la valeur d'une clé que l'application peut invoquer. Dans le cas du cache, l'application est la seule à communiquer avec le stockage de sauvegarde et donc à mettre à jour le cache. Cependant, avec le cache de lecture, il y a deux options pour traiter les enregistrements: le cache écrit et le cache écrit. Le caching par écrit est une stratégie dans laquelle une mise à jour du cache se propage immédiatement au magasin de sauvegarde. Chaque fois qu'un cache est mis à jour, le cache met synchroniquement à jour le magasin de sauvegarde avec la valeur cachée. La latence d'écriture du cache par écrit est dominée par la latence d'écriture au magasin de sauvegarde, ce qui peut être significatif. Comme le montre la figure 3, une application met à jour un cache à l'aide d'une interface fournie par le cache avec une clé et une paire de valeurs. Le cache met à jour son état avec la nouvelle valeur, met à jour la base de données avec la nouvelle valeur et attend que la base de données fasse la mise à jour jusqu'à ce qu'elle reconnaisse la Cependant, pour les caches non transactionnelles, le cache et le stockage de sauvegarde peuvent ne pas être synchronisés en présence d'erreurs. Par exemple, si l'écriture au cache réussit, mais l'écriture au stockage de sauvegarde échoue, les deux seront hors de synchronisation. Bien sûr, un cache d'écriture peut fournir des garanties transactionnelles en échangeant une certaine latence pour s'assurer que le cache et la base de données sont à la fois mises à jour ou pas. Comme avec un cache de lecture, le cache d'écriture suppose que le cache peut se connecter à la base de données et transformer une valeur de cache en une requête de base de données. Par exemple, si vous cachez des données utilisateur où l'identifiant utilisateur sert de clé et un document JSON représente la valeur, le cache doit pouvoir transformer la représentation JSON des informations utilisateur en une mise à jour de base de données. Avec le caching par écrit, la solution la plus simple est souvent de stocker le JSON dans la base de données. Le principal inconvénient du caching par écrit est la latence associée aux mises à jour du cache, ce qui est essentiellement équivalent à la latence de la base de données. Écrire derrière le caching En d'autres termes, avec le cache écrit-derrière, le cache peut accepter plusieurs mises à jour avant de mettre à jour le stockage de sauvegarde, comme indiqué dans la Figure 4, où le cache accepte trois mises à jour avant de mettre à jour la base de données. La latence d'écriture d'un cache écrit-derrière est inférieure à celle d'un cache écrit-derrière parce que le cache de sauvegarde est mis à jour de manière asynchrone. C'est-à-dire que le cache peut reconnaître l'écriture immédiatement à l'application, ce qui entraîne une écriture à faible latence, puis effectuer la mise à jour du cache de sauvegarde en arrière-plan. Cependant, l'inconvénient du cache écrit-derrière est que vous perdez le support de la transaction parce que le cache ne peut plus garantir que le cache et la base de données sont en synchronisation. En outre, le cache écrit-derrière peut réduire la durabilité, ce qui est la garantie que vous Le client caching Une stratégie de cache client-side signifie avoir le cache à la couche client au sein de votre application. Bien que les serveurs de cache tels que Redis utilisent le cache in-memory, l'application doit communiquer sur le réseau pour accéder au cache via le protocole Redis. Si l'application est un service exécuté dans un centre de données, un serveur cache est excellent pour le caching car le tour du réseau au sein d'un centre de données est rapide et la complexité du cache est dans le cache lui-même. Cependant, la latence de la dernière mile peut encore être un facteur important dans l'expérience utilisateur sur un appareil, ce qui explique pourquoi le caching client-side est si lucratif. Avec le caching du côté client, une combinaison de caching de lecture et d'écriture est optimale du point de vue de la latence, car les lectures et les écritures sont rapides. Bien sûr, votre client ne pourra généralement pas se connecter directement à la base de données, mais accède à la base de données indirectement via un serveur proxy ou un serveur API. Pour de nombreuses applications qui nécessitent un caching client-side à faible latence, l'approche locale-first à la réplication peut être plus pratique. Mais pour le caching lecture simple, le caching client-side peut être une bonne solution pour atteindre une latence faible. Bien sûr, le caching client-side a également un compromis : il peut augmenter la consommation de mémoire de l'application parce que vous avez besoin d'espace pour le cache. Le caching distribué Jusqu'à présent, nous n'avons discuté que de la mise en cache comme si une seule instance de mise en cache existait. Par exemple, vous utilisez un cache dans l'application ou un seul serveur Redis pour stocker des requêtes à partir d'une base de données PostgreSQL. Cependant, vous avez souvent besoin de plusieurs copies des données pour réduire la latence géographique à travers différents emplacements ou évoluer pour accueillir votre charge de travail. Avec une telle mise en cache distribuée, vous avez de nombreuses instances de la mise en cache qui fonctionnent indépendamment ou dans un groupe de mise en cache. Avec la mise en cache distribuée, vous avez beaucoup des mêmes complications et considérations que celles décrites dans le chapitre 4 sur la réplication et le chapitre 5 sur la partition. Avec la mise en cache distribuée, vous ne voulez pas combiner toutes les données mises en cache sur chaque instance, mais au lieu de cela, vous avez des données cachées divisées entre les nœuds. De même, vous pouvez reproduire les partitions sur plusieurs instances pour une haute disponibilité et une latence d'accès réduite. Dans l’ensemble, le caching distribué est une intersection des avantages et des problèmes du caching, de la partitionnement et de la réplication, alors faites attention si vous allez avec cela. *** à Pour continuer à lire, à partir de ScyllaDB ou . Télécharger le chapitre 3 Latency extrait gratuitement Achetez le livre complet de Manning À propos de Cynthia Dunlop Cynthia est directrice générale de la stratégie de contenu chez ScyllaDB. Elle écrit sur le développement de logiciels et l'ingénierie de la qualité depuis plus de 20 ans.