Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
La mise en cache est une technique courante qui vise à améliorer les performances et l’extensibilité d’un système. Il met en cache les données en copiant temporairement les données fréquemment sollicitées dans un stockage rapide situé à proximité de l’application. Si cet espace de stockage rapide des données se trouve plus près de l’application que la source d’origine, la mise en cache peut améliorer sensiblement les temps de réponse des applications clientes en fournissant les données plus rapidement.
La mise en cache est la plus efficace lorsqu’une instance cliente lit à plusieurs reprises les mêmes données, en particulier si toutes les conditions suivantes s’appliquent au magasin de données d’origine :
- Elle reste relativement statique.
- Il est lent par rapport à la vitesse du cache.
- Il est soumis à un niveau élevé de contention.
- Il est loin lorsque la latence du réseau peut entraîner un ralentissement de l’accès.
Mise en cache dans les applications distribuées
Les applications distribuées implémentent généralement l’une ou l’autre des stratégies suivantes lors de la mise en cache des données :
- Ils utilisent un cache privé, où les données sont conservées localement sur l’ordinateur exécutant une instance d’une application ou d’un service.
- Ils utilisent un cache partagé, servant de source commune accessible par plusieurs processus et machines.
Dans les deux cas, la mise en cache peut être effectuée côté client et côté serveur. La mise en cache côté client est effectuée par le processus qui fournit l’interface utilisateur pour un système, tel qu’un navigateur web ou une application de bureau. La mise en cache côté serveur est effectuée par le processus qui fournit les services métier qui s’exécutent à distance.
Mise en cache privée
Le type de cache le plus simple est un magasin en mémoire. Il est conservé dans l’espace d’adressage d’un seul processus et accessible directement par le code qui s’exécute dans ce processus. Ce type de cache est rapide à accéder. Il peut également fournir un moyen efficace de stocker des quantités modestes de données statiques. La taille d’un cache est généralement limitée par la quantité de mémoire disponible sur l’ordinateur qui héberge le processus.
Si vous devez mettre en cache plus d’informations que ce qui est physiquement possible en mémoire, vous pouvez écrire des données mises en cache dans le système de fichiers local. Ce processus est plus lent à accéder aux données conservées en mémoire, mais il doit toujours être plus rapide et plus fiable que la récupération de données sur un réseau.
Si vous avez plusieurs instances d’une application qui utilise ce modèle en cours d’exécution simultanément, chaque instance d’application possède son propre cache indépendant contenant sa propre copie des données.
Considérez un cache comme un instantané des données d’origine à un moment donné dans le passé. Si ces données ne sont pas statiques, il est probable que différentes instances d’application contiennent différentes versions des données dans leurs caches. Par conséquent, la même requête effectuée par ces instances peut retourner des résultats différents, comme illustré dans la figure 1.
Figure 1 : Utilisation d’un cache en mémoire dans différentes instances d’une application.
Mise en cache partagée
Si vous utilisez un cache partagé, cela peut aider à atténuer les problèmes que les données peuvent différer dans chaque cache, ce qui peut se produire avec la mise en cache en mémoire. La mise en cache partagée garantit que différentes instances d’application voient la même vue des données mises en cache. Il localise le cache dans un emplacement distinct, qui est généralement hébergé dans le cadre d’un service distinct, comme illustré dans la figure 2.
Figure 2 : Utilisation d’un cache partagé.
Un avantage important de l’approche de mise en cache partagée est la scalabilité qu’elle fournit. De nombreux services de cache partagé sont implémentés à l’aide d’un cluster de serveurs et utilisent des logiciels pour distribuer les données sur le cluster de manière transparente. Une instance d’application envoie simplement une requête au service de cache. L’infrastructure sous-jacente détermine l’emplacement des données mises en cache dans le cluster. Vous pouvez facilement mettre à l’échelle le cache en ajoutant d’autres serveurs.
Il existe deux inconvénients principaux de l’approche de mise en cache partagée :
- Le cache est plus lent à accéder, car il n’est plus conservé localement pour chaque instance d’application.
- L’exigence d’implémenter un service de cache distinct peut ajouter de la complexité à la solution.
Considérations relatives à l’utilisation de la mise en cache
Les sections suivantes décrivent plus en détail les considérations relatives à la conception et à l’utilisation d’un cache.
Décider quand mettre en cache des données
La mise en cache peut considérablement améliorer les performances, l’extensibilité et la disponibilité. Plus vous disposez de données et plus le nombre d’utilisateurs qui doivent accéder à ces données, plus les avantages de la mise en cache sont accrus. La mise en cache réduit la latence et la contention associées à la gestion de gros volumes de requêtes simultanées dans le magasin de données d’origine.
Par exemple, une base de données peut prendre en charge un nombre limité de connexions simultanées. Toutefois, la récupération de données à partir d’un cache partagé, plutôt que la base de données sous-jacente, permet à une application cliente d’accéder à ces données même si le nombre de connexions disponibles est actuellement épuisé. En outre, si la base de données devient indisponible, les applications clientes peuvent continuer à utiliser les données conservées dans le cache.
Envisagez de mettre en cache les données qui sont lues fréquemment mais modifiées rarement (par exemple, les données qui ont une proportion plus élevée d’opérations de lecture que les opérations d’écriture). Toutefois, nous vous déconseillons d’utiliser le cache comme magasin faisant autorité des informations critiques. Au lieu de cela, assurez-vous que toutes les modifications que votre application ne peut pas se permettre de perdre sont toujours enregistrées dans un magasin de données persistant. Si le cache n’est pas disponible, votre application peut continuer à fonctionner à l’aide du magasin de données et vous ne perdrez pas d’informations importantes.
Déterminer comment mettre en cache efficacement les données
La clé d’utilisation d’un cache consiste à déterminer les données les plus appropriées à mettre en cache et à la mettre en cache au moment approprié. Les données peuvent être ajoutées au cache à la demande la première fois qu’elles sont récupérées par une application. L’application doit extraire les données une seule fois à partir du magasin de données, et cet accès ultérieur peut être satisfait à l’aide du cache.
Sinon, un cache peut être partiellement ou entièrement rempli avec des données à l’avance, généralement au démarrage de l’application (approche appelée amorçage). Toutefois, il est peut-être déconseillé d’implémenter l’amorçage pour un cache volumineux, car cette approche peut imposer une charge soudaine et élevée sur le magasin de données d’origine lorsque l’application commence à s’exécuter.
Souvent, une analyse des modèles d’utilisation peut vous aider à décider s’il faut remplir entièrement ou partiellement un cache et choisir les données à mettre en cache. Par exemple, vous pouvez amorçage du cache avec les données de profil utilisateur statiques pour les clients qui utilisent l’application régulièrement (peut-être tous les jours), mais pas pour les clients qui utilisent l’application une seule fois par semaine.
La mise en cache fonctionne généralement correctement avec les données qui sont immuables ou qui changent rarement. Les exemples incluent des informations de référence telles que des informations de produit et de tarification dans une application de commerce électronique ou des ressources statiques partagées coûteuses à construire. Certaines ou toutes ces données peuvent être chargées dans le cache au démarrage de l’application pour réduire la demande sur les ressources et améliorer les performances. Vous pouvez également avoir un processus en arrière-plan qui met régulièrement à jour les données de référence dans le cache pour vous assurer qu’il est up-to-date. Ou bien, le processus en arrière-plan peut actualiser le cache lorsque les données de référence changent.
La mise en cache est moins utile pour les données dynamiques, bien qu’il existe des exceptions à cette considération (consultez la section Mettre en cache les données hautement dynamiques plus loin dans cet article pour plus d’informations). Lorsque les données d’origine changent régulièrement, les informations mises en cache deviennent obsolètes rapidement ou la surcharge de synchronisation du cache avec le magasin de données d’origine réduit l’efficacité de la mise en cache.
Un cache n’a pas besoin d’inclure les données complètes d’une entité. Par exemple, si un élément de données représente un objet à valeurs multiples, tel qu’un client bancaire avec un nom, une adresse et un solde de compte, certains de ces éléments peuvent rester statiques, tels que le nom et l’adresse. D’autres éléments, tels que le solde du compte, peuvent être plus dynamiques. Dans ces situations, il peut être utile de mettre en cache les parties statiques des données et de récupérer (ou de calculer) uniquement les informations restantes quand elles sont requises.
Nous vous recommandons d’effectuer des tests de performances et une analyse de l’utilisation pour déterminer si le chargement à la demande ou le chargement à la demande du cache, ou une combinaison des deux, est approprié. La décision doit être basée sur la volatilité et le modèle d’utilisation des données. L’utilisation du cache et l’analyse des performances sont importantes dans les applications qui rencontrent des charges lourdes et doivent être hautement évolutives. Par exemple, dans des scénarios hautement évolutifs, vous pouvez amorçage du cache pour réduire la charge sur le magasin de données aux heures de pointe.
La mise en cache peut également être utilisée pour éviter les calculs répétés pendant l’exécution de l’application. Si une opération transforme des données ou effectue un calcul compliqué, elle peut enregistrer les résultats de l’opération dans le cache. Si le même calcul est requis par la suite, l’application peut simplement récupérer les résultats à partir du cache.
Une application peut modifier les données conservées dans un cache. Toutefois, nous vous recommandons de considérer le cache comme un magasin de données temporaire qui pourrait disparaître à tout moment. Ne stockez pas de données précieuses dans le cache uniquement ; veillez également à conserver les informations dans le magasin de données d’origine. Cela signifie que si le cache devient indisponible, vous réduisez le risque de perte de données.
Mettre en cache des données hautement dynamiques
Lorsque vous stockez rapidement des informations dans un magasin de données persistant, il peut imposer une surcharge sur le système. Par exemple, considérez un appareil qui signale continuellement l’état ou une autre mesure. Si une application choisit de ne pas mettre en cache ces données en fonction du fait que les informations mises en cache seront presque toujours obsolètes, la même considération peut être vraie lors du stockage et de la récupération de ces informations à partir du magasin de données. Dans le temps nécessaire à l’enregistrement et à l’extraction de ces données, il peut avoir changé.
Dans une situation telle que celle-ci, tenez compte des avantages du stockage des informations dynamiques directement dans le cache plutôt que dans le magasin de données persistant. Si les données ne sont pas critiques et ne nécessitent pas d’audit, cela n’a pas d’importance si la modification occasionnelle est perdue.
Gérer l’expiration des données dans un cache
Dans la plupart des cas, les données conservées dans un cache sont une copie des données conservées dans le magasin de données d’origine. Les données du magasin de données d’origine peuvent changer une fois qu’elles ont été mises en cache, ce qui entraîne l’obsolescence des données mises en cache. De nombreux systèmes de mise en cache vous permettent de configurer le cache pour expirer les données et de réduire la période pendant laquelle les données peuvent être obsolètes.
Lorsque les données mises en cache expirent, elles sont supprimées du cache et l’application doit récupérer les données du magasin de données d’origine (elle peut remettre les informations nouvellement extraites dans le cache). Vous pouvez définir une stratégie d’expiration par défaut lorsque vous configurez le cache. Dans de nombreux services de cache, vous pouvez également stipuler la période d’expiration des objets individuels lorsque vous les stockez par programmation dans le cache. Certains caches vous permettent de spécifier la période d’expiration en tant que valeur absolue ou comme valeur glissante qui entraîne la suppression de l’élément du cache s’il n’est pas accessible dans l’heure spécifiée. Ce paramètre remplace toute stratégie d’expiration à l’échelle du cache, mais uniquement pour les objets spécifiés.
Note
Tenez compte de la période d’expiration du cache et des objets qu’il contient avec soin. Si vous le faites trop court, les objets expirent trop rapidement et vous réduisez les avantages de l’utilisation du cache. Si vous faites trop longtemps la période, vous risquez que les données deviennent obsolètes.
Il est également possible que le cache se remplisse si les données sont autorisées à rester résidentes pendant longtemps. Dans ce cas, toutes les demandes d’ajout de nouveaux éléments au cache peuvent entraîner la suppression forcée de certains éléments dans un processus appelé éviction. Les services de cache suppriment généralement les données au moins récemment utilisées (LRU), mais vous pouvez généralement remplacer cette stratégie et empêcher les éléments d’être supprimés. Toutefois, si vous adoptez cette approche, vous risquez de dépasser la mémoire disponible dans le cache. Une application qui tente d’ajouter un élément au cache échoue avec une exception.
Certaines implémentations de mise en cache peuvent fournir des stratégies d’éviction supplémentaires. Il existe plusieurs types de stratégies d’éviction. Voici quelques-uns des éléments suivants :
- Une stratégie utilisée récemment (dans l’attente que les données ne seront pas requises à nouveau).
- Une stratégie de premier entrée dans le premier sorti (les données les plus anciennes sont supprimées en premier).
- Stratégie de suppression explicite basée sur un événement déclenché (par exemple, les données en cours de modification).
Invalider les données dans un cache côté client
Les données conservées dans un cache côté client sont généralement considérées comme extérieures aux auspices du service qui fournissent les données au client. Un service ne peut pas forcer directement un client à ajouter ou supprimer des informations d’un cache côté client.
Cela signifie qu’il est possible pour un client qui utilise un cache mal configuré pour continuer à utiliser des informations obsolètes. Par exemple, si les stratégies d’expiration du cache ne sont pas correctement implémentées, un client peut utiliser des informations obsolètes mises en cache localement lorsque les informations de la source de données d’origine ont changé.
Si vous créez une application web qui sert des données via une connexion HTTP, vous pouvez forcer implicitement un client web (tel qu’un navigateur ou un proxy web) à extraire les informations les plus récentes. Pour ce faire, si une ressource est mise à jour par une modification de l’URI de cette ressource. Les clients web utilisent généralement l’URI d’une ressource comme clé dans le cache côté client. Par conséquent, si l’URI change, le client web ignore les versions précédemment mises en cache d’une ressource et récupère la nouvelle version à la place.
Gestion de l’accès concurrentiel dans un cache
Les caches sont souvent conçus pour être partagés par plusieurs instances d’une application. Chaque instance d’application peut lire et modifier des données dans le cache. Par conséquent, les mêmes problèmes d’accès concurrentiel qui surviennent avec n’importe quel magasin de données partagé s’appliquent également à un cache. Dans un cas où une application doit modifier les données conservées dans le cache, vous devrez peut-être vous assurer que les mises à jour effectuées par une instance de l’application ne remplacent pas les modifications apportées par une autre instance.
Selon la nature des données et la probabilité de collisions, vous pouvez adopter l’une des deux approches de concurrence :
- Optimistic. Immédiatement avant la mise à jour des données, l’application vérifie si les données du cache ont changé depuis sa récupération. Si les données sont toujours identiques, la modification peut être apportée. Sinon, l’application doit décider s’il faut la mettre à jour. (La logique métier qui pilote cette décision est spécifique à l’application.) Cette approche convient aux situations où les mises à jour sont peu fréquentes ou où les collisions sont peu susceptibles de se produire.
- Pessimistic. Lorsqu’elle récupère les données, l’application le verrouille dans le cache pour empêcher une autre instance de la modifier. Ce processus garantit que les collisions ne peuvent pas se produire, mais elles peuvent également bloquer d’autres instances qui doivent traiter les mêmes données. La concurrence pessimiste peut affecter l’extensibilité d’une solution et est recommandée uniquement pour les opérations de courte durée. Cette approche peut être appropriée pour les situations où les collisions sont plus probables, en particulier si une application met à jour plusieurs éléments dans le cache et doit s’assurer que ces modifications sont appliquées de manière cohérente.
Implémenter la haute disponibilité et la scalabilité, et améliorer les performances
Évitez d’utiliser un cache comme référentiel principal de données ; il s’agit du rôle du magasin de données d’origine à partir duquel le cache est rempli. Le magasin de données d’origine est chargé de garantir la persistance des données.
Veillez à ne pas introduire de dépendances critiques sur la disponibilité d’un service de cache partagé dans vos solutions. Une application doit pouvoir continuer à fonctionner si le service qui fournit le cache partagé n’est pas disponible. L’application ne doit pas répondre ou échouer en attendant que le service de cache reprend.
Par conséquent, l’application doit être prête à détecter la disponibilité du service de cache et à revenir au magasin de données d’origine si le cache est inaccessible. Le modèleCircuit-Breaker est utile pour gérer ce scénario. Le service qui fournit le cache peut être récupéré et, une fois qu’il est disponible, le cache peut être réalimenté à mesure que les données sont lues à partir du magasin de données d’origine, en suivant une stratégie telle que le modèle cache-aside.
Toutefois, l’extensibilité du système peut être affectée si l’application revient au magasin de données d’origine lorsque le cache est temporairement indisponible. Pendant la récupération du magasin de données, le magasin de données d’origine peut être débordé de demandes de données, ce qui entraîne des délais d’expiration et des connexions ayant échoué.
Envisagez d’implémenter un cache local privé dans chaque instance d’une application, ainsi que le cache partagé auquel toutes les instances d’application accèdent. Lorsque l’application récupère un élément, elle peut d’abord vérifier dans son cache local, puis dans le cache partagé et enfin dans le magasin de données d’origine. Le cache local peut être rempli à l’aide des données dans le cache partagé ou dans la base de données si le cache partagé n’est pas disponible.
Cette approche nécessite une configuration minutieuse pour empêcher le cache local de devenir trop obsolète en ce qui concerne le cache partagé. Toutefois, le cache local agit comme une mémoire tampon si le cache partagé est inaccessible. La figure 3 montre cette structure.
Figure 3 : Utilisation d’un cache privé local avec un cache partagé.
Pour prendre en charge les grands caches qui contiennent des données relativement longues, certains services de cache offrent une option de haute disponibilité qui implémente le basculement automatique si le cache devient indisponible. Cette approche implique généralement la réplication des données mises en cache stockées sur un serveur de cache principal vers un serveur de cache secondaire et le basculement vers le serveur secondaire si le serveur principal échoue ou si la connectivité est perdue.
Pour réduire la latence associée à l’écriture dans plusieurs destinations, la réplication sur le serveur secondaire peut se produire de manière asynchrone lorsque les données sont écrites dans le cache sur le serveur principal. Cette approche entraîne la possibilité que certaines informations mises en cache soient perdues en cas d’échec, mais la proportion de ces données doit être faible, par rapport à la taille globale du cache.
Si un cache partagé est volumineux, il peut être utile de partitionner les données mises en cache entre les nœuds afin de réduire les chances de contention et d’améliorer l’extensibilité. De nombreux caches partagés prennent en charge la possibilité d’ajouter (et de supprimer) dynamiquement des nœuds et de rééquilibrer les données entre les partitions. Cette approche peut impliquer le clustering, dans lequel la collection de nœuds est présentée aux applications clientes comme un cache unique et fluide. Toutefois, en interne, les données sont dispersées entre les nœuds à la suite d’une stratégie de distribution prédéfinie qui équilibre uniformément la charge. Pour plus d’informations sur les stratégies de partitionnement possibles, consultez les instructions de partitionnement des données.
Le clustering peut également augmenter la disponibilité du cache. En cas d’échec d’un nœud, le reste du cache est toujours accessible. Le clustering est fréquemment utilisé conjointement avec la réplication et le basculement. Chaque nœud peut être répliqué et le réplica peut être rapidement mis en ligne en cas d’échec du nœud.
De nombreuses opérations de lecture et d’écriture sont susceptibles d’impliquer des valeurs ou des objets de données uniques. Toutefois, il peut être nécessaire de stocker ou de récupérer rapidement de grands volumes de données. Par exemple, l’amorçage d’un cache peut impliquer l’écriture de centaines ou de milliers d’éléments dans le cache. Une application peut également avoir besoin de récupérer un grand nombre d’éléments connexes à partir du cache dans le cadre de la même requête.
De nombreux caches à grande échelle fournissent des opérations de traitement par lots à ces fins. Cela permet à une application cliente de empaqueter un grand volume d’éléments dans une seule requête et réduit la surcharge associée à l’exécution d’un grand nombre de petites requêtes.
Mise en cache et cohérence éventuelle
Pour que le modèle cache-aside fonctionne, l’instance de l’application qui remplit le cache doit avoir accès à la version la plus récente et cohérente des données. Dans un système qui implémente la cohérence éventuelle (par exemple, un magasin de données répliqué), cela peut ne pas être le cas.
Une instance d’une application peut modifier un élément de données et invalider la version mise en cache de cet élément. Une autre instance de l’application peut tenter de lire cet élément à partir d’un cache, ce qui provoque une absence de cache, de sorte qu’elle lit les données du magasin de données et l’ajoute au cache. Toutefois, si le magasin de données n’a pas été entièrement synchronisé avec les autres réplicas, l’instance de l’application peut lire et remplir le cache avec l’ancienne valeur.
Pour plus d’informations sur la gestion de la cohérence des données, consultez l’primeur de cohérence des données.
Protéger les données mises en cache
Quel que soit le service de cache que vous utilisez, envisagez de protéger les données conservées dans le cache contre un accès non autorisé. Il existe deux préoccupations principales :
- Confidentialité des données dans le cache.
- Confidentialité des données à mesure qu’elles circulent entre le cache et l’application qui utilise le cache.
Pour protéger les données dans le cache, le service de cache peut implémenter un mécanisme d’authentification qui nécessite que les applications spécifient les détails suivants :
- Quelles identités peuvent accéder aux données dans le cache.
- Quelles opérations (lecture et écriture) ces identités sont autorisées à effectuer.
Pour réduire la surcharge associée à la lecture et à l’écriture de données, une fois qu’une identité a reçu un accès en écriture ou en lecture au cache, cette identité peut utiliser n’importe quelle donnée dans le cache.
Si vous devez restreindre l’accès aux sous-ensembles des données mises en cache, vous pouvez effectuer l’une des approches suivantes :
- Fractionnez le cache en partitions (à l’aide de différents serveurs de cache) et accordez uniquement l’accès aux identités pour les partitions qu’ils doivent être autorisés à utiliser.
- Chiffrez les données de chaque sous-ensemble à l’aide de clés différentes et fournissez les clés de chiffrement uniquement aux identités qui doivent avoir accès à chaque sous-ensemble. Une application cliente peut toujours être en mesure de récupérer toutes les données dans le cache, mais elle ne pourra déchiffrer que les données pour lesquelles elle possède les clés.
Vous devez également protéger les données au fur et à mesure qu’elles circulent dans et hors du cache. Pour ce faire, vous dépendez des fonctionnalités de sécurité fournies par l’infrastructure réseau que les applications clientes utilisent pour vous connecter au cache. Si le cache est implémenté à l’aide d’un serveur sur site au sein de la même organisation qui héberge les applications clientes, l’isolation du réseau lui-même peut ne pas nécessiter de mesures supplémentaires. Si le cache se trouve à distance et nécessite une connexion TCP ou HTTP sur un réseau public (par exemple, Internet), envisagez d’implémenter SSL.
Considérations relatives à l’implémentation de la mise en cache dans Azure
Le cache Azure pour Redis est une implémentation du cache Redis open source qui s’exécute en tant que service dans un centre de données Azure. Il fournit un service de mise en cache accessible à partir de n’importe quelle application Azure, que l’application soit implémentée en tant que service cloud, site web ou à l’intérieur d’une machine virtuelle Azure. Les caches peuvent être partagés par les applications clientes qui ont la clé d’accès appropriée.
Azure Cache pour Redis est une solution de mise en cache hautes performances qui fournit la disponibilité, la scalabilité et la sécurité. Il s’exécute généralement en tant que service réparti sur une ou plusieurs machines dédiées. Il tente de stocker autant d’informations que possible en mémoire pour garantir un accès rapide. Cette architecture vise à fournir une faible latence et un débit élevé en réduisant la nécessité d’effectuer des opérations d’E/S lentes.
Azure Cache pour Redis est compatible avec de nombreuses API utilisées par les applications clientes. Si vous disposez d’applications existantes qui utilisent déjà Azure Cache pour Redis s’exécutant localement, le Cache Azure pour Redis fournit un chemin de migration rapide vers la mise en cache dans le cloud.
Fonctionnalités de Redis
Redis est plus qu’un serveur de cache simple. Il fournit une base de données distribuée en mémoire avec un ensemble de commandes étendu qui prend en charge de nombreux scénarios courants. Ces éléments sont décrits plus loin dans ce document, dans la section Utilisation de la mise en cache Redis. Cette section récapitule certaines des principales fonctionnalités fournies par Redis.
Redis en tant que base de données en mémoire
Redis prend en charge les opérations de lecture et d’écriture. Dans Redis, les écritures peuvent être protégées contre les défaillances système en étant stockées régulièrement dans un fichier d’instantané local ou dans un fichier journal d’ajout uniquement. Cette situation n’est pas le cas dans de nombreux caches, qui doivent être considérés comme des magasins de données transitoires.
Toutes les écritures sont asynchrones et ne empêchent pas les clients de lire et d’écrire des données. Lorsque Redis commence à s’exécuter, il lit les données à partir de l’instantané ou du fichier journal et l’utilise pour construire le cache en mémoire. Pour plus d’informations, consultez Persistance Redis sur le site Web de Redis.
Note
Redis ne garantit pas que toutes les écritures sont enregistrées en cas de défaillance catastrophique, mais au pire, vous risquez de perdre seulement quelques secondes de données. N’oubliez pas qu’un cache n’est pas destiné à faire office de source de données faisant autorité et qu’il incombe aux applications qui utilisent le cache de s’assurer que les données critiques sont enregistrées correctement dans un magasin de données approprié. Pour plus d’informations, consultez le modèle Cache-aside.
Types de données Redis
Redis est un magasin clé-valeur, où les valeurs peuvent contenir des types simples ou des structures de données complexes telles que des hachages, des listes et des ensembles. Il prend en charge un ensemble d’opérations atomiques sur ces types de données. Les clés peuvent être permanentes ou marquées avec une durée de vie limitée, à quel moment la clé et sa valeur correspondante sont automatiquement supprimées du cache. Pour plus d’informations sur les clés et les valeurs Redis, consultez la page Présentation des types de données et des abstractions Redis sur le site web De Redis.
Réplication et clustering Redis
Redis prend en charge la réplication principale/subordonnée pour garantir la disponibilité et maintenir le débit. Les opérations d’écriture dans un nœud principal Redis sont répliquées sur un ou plusieurs nœuds subordonnés. Les opérations de lecture peuvent être traitées par le principal ou l’un des subordonnés.
Si vous disposez d’une partition réseau, les subordonnés peuvent continuer à servir des données, puis resynchroniser de manière transparente avec le serveur principal lorsque la connexion est rétablie. Pour plus d’informations, consultez la page Réplication sur le site web de Redis.
Redis fournit également un clustering, qui vous permet de partitionner les données de manière transparente en partitions sur des serveurs et de répartir la charge. Cette fonctionnalité améliore l’extensibilité, car de nouveaux serveurs Redis peuvent être ajoutés et les données réparties à mesure que la taille du cache augmente.
De plus, chaque serveur du cluster peut être répliqué à l’aide de la réplication principale/subordonnée. Cela garantit la disponibilité sur chaque nœud du cluster. Pour plus d’informations sur le clustering et le partitionnement, consultez la page du didacticiel sur le cluster Redis sur le site web De Redis.
Utilisation de la mémoire Redis
Un cache Redis a une taille limitée qui dépend des ressources disponibles sur l’ordinateur hôte. Lorsque vous configurez un serveur Redis, vous pouvez spécifier la quantité maximale de mémoire qu’il peut utiliser. Vous pouvez également configurer une clé dans un cache Redis pour qu’elle ait un délai d’expiration, après quoi elle est automatiquement supprimée du cache. Cette fonctionnalité peut aider à empêcher le cache en mémoire de remplir des données anciennes ou obsolètes.
À mesure que la mémoire se remplit, Redis peut supprimer automatiquement les clés et leurs valeurs en fonction de différentes stratégies. La valeur par défaut est la moins récemment utilisée (LRU), mais vous pouvez également choisir d'autres options, comme évincer des clés au hasard ou désactiver complètement l'éviction. Dans ce cas, les tentatives d’ajout d’éléments au cache échouent s’il est plein. Pour plus d’informations, consultez Utiliser Redis comme cache LRU.
Transactions et lots Redis
Redis permet à une application cliente d’envoyer une série d’opérations qui lisent et écrivent des données dans le cache en tant que transaction atomique. Toutes les commandes de la transaction sont garanties de s’exécuter de manière séquentielle, sans qu'aucune commande émise par d'autres clients simultanés ne s'intercale entre elles.
Toutefois, ces transactions ne sont pas vraies, car une base de données relationnelle les effectuerait. Le traitement des transactions se compose de deux phases : la première est lorsque les commandes sont mises en file d’attente, et la seconde est lorsque les commandes sont exécutées. Pendant la phase de mise en file d’attente de commandes, les commandes qui composent la transaction sont envoyées par le client. Si une sorte d’erreur se produit à ce stade (par exemple, une erreur de syntaxe ou le mauvais nombre de paramètres), Redis refuse de traiter l’intégralité de la transaction et l’ignore.
Pendant la phase d’exécution, Redis exécute chaque commande mise en file d’attente en séquence. Si une commande échoue pendant cette phase, Redis continue avec la commande mise en file d’attente suivante et ne restaure pas les effets des commandes qui ont déjà été exécutées. Cette forme simplifiée de transaction permet de maintenir les performances et d’éviter les problèmes de performances causés par la contention.
Redis implémente une forme de verrouillage optimiste pour aider à maintenir la cohérence. Pour plus d’informations sur les transactions et le verrouillage avec Redis, visitez la page Transactions sur le site web De Redis.
Redis prend également en charge le traitement par lots nontransactionnel de requêtes. Le protocole Redis que les clients utilisent pour envoyer des commandes à un serveur Redis permet à un client d’envoyer une série d’opérations dans le cadre de la même requête. Cela peut aider à réduire la fragmentation des paquets sur le réseau. Lorsque le traitement par lots est exécuté, chaque commande s’exécute. Si l’une de ces commandes est incorrecte, elles sont rejetées (qui ne se produisent pas avec une transaction), mais les commandes restantes sont exécutées. Il n’existe pas non plus de garantie concernant l’ordre des commandes dans le processus de traitement par lots.
Sécurité Redis
Redis se concentre uniquement sur la fourniture d’un accès rapide aux données et est conçu pour s’exécuter à l’intérieur d’un environnement approuvé accessible uniquement par des clients approuvés. Redis prend en charge un modèle de sécurité limité basé sur l’authentification par mot de passe. (Il est possible de supprimer complètement l’authentification, bien que nous ne le recommandons pas.)
Tous les clients authentifiés partagent le même mot de passe global et ont accès aux mêmes ressources. Si vous avez besoin d’une sécurité de connexion plus complète, vous devez implémenter votre propre couche de sécurité devant le serveur Redis, et toutes les demandes clientes doivent passer par cette couche supplémentaire. Redis ne doit pas être directement exposé aux clients non approuvés ou non authentifiés.
Vous pouvez restreindre l’accès aux commandes en les désactivant ou en les renommant (et en fournissant uniquement aux clients privilégiés les nouveaux noms).
Redis ne prend pas directement en charge une forme de chiffrement des données. Par conséquent, tous les encodages doivent être effectués par les applications clientes. En outre, Redis ne fournit aucune forme de sécurité du transport. Si vous devez protéger les données au fur et à mesure qu’elles circulent sur le réseau, nous vous recommandons d’implémenter un proxy SSL.
Pour plus d’informations, consultez la page de sécurité Redis sur le site web De Redis.
Note
Azure Cache pour Redis fournit sa propre couche de sécurité via laquelle les clients se connectent. Les serveurs Redis sous-jacents ne sont pas exposés au réseau public.
Cache Redis Azure
Azure Cache pour Redis fournit l’accès aux serveurs Redis hébergés dans un centre de données Azure. Il agit comme une façade qui assure le contrôle d’accès et la sécurité. Vous pouvez approvisionner un cache à l’aide du portail Azure.
Le portail fournit plusieurs configurations prédéfinies. Ces configurations vont d’un cache de 53 Go exécuté en tant que service dédié qui prend en charge les communications SSL (pour la confidentialité) et la réplication maître/subordonné avec un contrat de niveau de service (SLA) de 99,9% disponibilité, jusqu’à un cache de 250 Mo sans réplication (aucune garantie de disponibilité) s’exécutant sur du matériel partagé.
À l’aide du portail Azure, vous pouvez également configurer la stratégie d’éviction du cache et contrôler l’accès au cache en ajoutant des utilisateurs aux rôles fournis. Ces rôles, qui définissent les opérations que les membres peuvent effectuer, incluent Propriétaire, Contributeur et Lecteur. Par exemple, les membres du rôle Propriétaire ont un contrôle total sur le cache (y compris la sécurité) et son contenu, les membres du rôle Contributeur peuvent lire et écrire des informations dans le cache, et les membres du rôle Lecteur peuvent uniquement récupérer des données du cache.
La plupart des tâches administratives sont effectuées via le portail Azure. Pour cette raison, la plupart des commandes d’administration disponibles dans la version standard de Redis ne sont pas disponibles, notamment la possibilité de modifier la configuration par programmation, d’arrêter le serveur Redis, de configurer des subordonnés supplémentaires ou d’enregistrer de force des données sur le disque.
Le portail Azure comprend un affichage graphique pratique qui vous permet de surveiller les performances du cache. Par exemple, vous pouvez afficher le nombre de connexions effectuées, le nombre de requêtes effectuées, le volume de lectures et d’écritures, ainsi que le nombre d’accès au cache par rapport aux absences de cache. À l’aide de ces informations, vous pouvez déterminer l’efficacité du cache et, le cas échéant, basculer vers une autre configuration ou modifier la stratégie d’éviction.
En outre, vous pouvez créer des alertes qui envoient des messages électroniques à un administrateur si une ou plusieurs métriques critiques se trouvent en dehors d’une plage attendue. Par exemple, vous pouvez alerter un administrateur si le nombre d’absences de cache dépasse une valeur spécifiée au cours de la dernière heure, car cela signifie que le cache peut être trop petit ou que les données peuvent être supprimées trop rapidement.
Vous pouvez également surveiller l’utilisation du processeur, de la mémoire et du réseau pour le cache.
Pour plus d’informations et d’exemples montrant comment créer et configurer un Cache Azure pour Redis, visitez la page Lap autour d’Azure Cache pour Redis sur le blog Azure.
Mise en cache de l’état de session et de la sortie HTML
Si vous générez ASP.NET applications web qui s’exécutent à l’aide de rôles web Azure, vous pouvez enregistrer les informations d’état de session et la sortie HTML dans un cache Azure pour Redis. Le fournisseur d’état de session pour Azure Cache pour Redis vous permet de partager des informations de session entre différentes instances d’une application web ASP.NET et est très utile dans les situations de batterie de serveurs web où l’affinité client-serveur n’est pas disponible et la mise en cache des données de session en mémoire ne serait pas appropriée.
L’utilisation du fournisseur d’état de session avec Azure Cache pour Redis offre plusieurs avantages, notamment :
- Partage de l’état de session avec un grand nombre d’instances de ASP.NET applications web.
- Fournir une scalabilité améliorée.
- Prise en charge de l’accès contrôlé et simultané aux mêmes données d’état de session pour plusieurs lecteurs et un seul enregistreur.
- Utilisation de la compression pour économiser de la mémoire et améliorer les performances du réseau.
Pour plus d’informations, consultez ASP.NET fournisseur d’état de session pour Azure Cache pour Redis.
Note
N’utilisez pas le fournisseur d’état de session pour Azure Cache pour Redis avec ASP.NET applications qui s’exécutent en dehors de l’environnement Azure. La latence d’accès au cache en dehors d’Azure peut éliminer les avantages en matière de performances de la mise en cache des données.
De même, le fournisseur de cache de sortie pour Azure Cache pour Redis vous permet d’enregistrer les réponses HTTP générées par une application web ASP.NET. L’utilisation du fournisseur de cache de sortie avec Azure Cache pour Redis peut améliorer les temps de réponse des applications qui affichent une sortie HTML complexe. Les instances d’application qui génèrent des réponses similaires peuvent utiliser les fragments de sortie partagés dans le cache plutôt que de générer cette sortie HTML à nouveau. Pour plus d’informations, consultez ASP.NET fournisseur de cache de sortie pour Azure Cache pour Redis.
Création d’un cache Redis personnalisé
Azure Cache pour Redis agit comme une façade des serveurs Redis sous-jacents. Si vous avez besoin d’une configuration avancée qui n’est pas couverte par le cache Redis Azure (par exemple, un cache de plus de 53 Go), vous pouvez générer et héberger vos propres serveurs Redis à l’aide de machines virtuelles Azure.
Il s’agit d’un processus potentiellement complexe, car vous devrez peut-être créer plusieurs machines virtuelles pour agir en tant que nœuds principaux et subordonnés si vous souhaitez implémenter la réplication. En outre, si vous souhaitez créer un cluster, vous avez besoin de plusieurs serveurs primaires et subordonnés. Une topologie de réplication en cluster minimale qui fournit un degré élevé de disponibilité et d’extensibilité comprend au moins six machines virtuelles organisées sous la forme de trois paires de serveurs principaux/subordonnés (un cluster doit contenir au moins trois nœuds principaux).
Chaque paire principale/subordonné doit être située à proximité pour réduire la latence. Toutefois, chaque ensemble de paires peut s’exécuter dans différents centres de données Azure situés dans différentes régions, si vous souhaitez localiser des données mises en cache proches des applications qui sont les plus susceptibles de l’utiliser. Pour obtenir un exemple de création et de configuration d’un nœud Redis s’exécutant en tant que machine virtuelle Azure, consultez Exécution de Redis sur une machine virtuelle Linux CentOS dans Azure.
Note
Si vous implémentez votre propre cache Redis de cette façon, vous êtes responsable de la supervision, de la gestion et de la sécurisation du service.
Partitionnement d’un cache Redis
Le partitionnement du cache implique le fractionnement du cache sur plusieurs ordinateurs. Cette structure vous offre plusieurs avantages par rapport à l’utilisation d’un serveur de cache unique, notamment :
- Création d’un cache beaucoup plus grand que celui pouvant être stocké sur un seul serveur.
- Distribution de données entre serveurs, amélioration de la disponibilité. Si un serveur échoue ou devient inaccessible, les données qu’il contient ne sont pas disponibles, mais les données sur les serveurs restants sont toujours accessibles. Pour un cache, cela n’est pas crucial, car les données mises en cache ne sont qu’une copie temporaire des données conservées dans une base de données. Les données mises en cache sur un serveur qui devient inaccessible peuvent être mises en cache sur un autre serveur à la place.
- Répartir la charge entre les serveurs, ce qui améliore les performances et l’extensibilité.
- Géolocalisation des données proches des utilisateurs qui y accèdent, réduisant ainsi la latence.
Pour un cache, la forme la plus courante de partitionnement est le partitionnement. Dans cette stratégie, chaque partition (ou partition) est un cache Redis à son propre droit. Les données sont dirigées vers une partition spécifique à l’aide de la logique de partitionnement, qui peut utiliser différentes approches pour distribuer les données. Le modèle de partitionnement fournit plus d’informations sur l’implémentation du partitionnement.
Pour implémenter le partitionnement dans un cache Redis, vous pouvez adopter l’une des approches suivantes :
- Routage des requêtes côté serveur. Dans cette technique, une application cliente envoie une requête à l’un des serveurs Redis qui composent le cache (probablement le serveur le plus proche). Chaque serveur Redis stocke les métadonnées qui décrivent la partition qu’il contient et contient également des informations sur les partitions qui se trouvent sur d’autres serveurs. Le serveur Redis examine la demande du client. Si elle peut être résolue localement, elle effectue l’opération demandée. Sinon, il transfère la requête au serveur approprié. Ce modèle est implémenté par le clustering Redis et est décrit plus en détail sur la page du didacticiel du cluster Redis sur le site web De Redis. Le clustering Redis est transparent pour les applications clientes, et d’autres serveurs Redis peuvent être ajoutés au cluster (et les données repartitionnée) sans avoir à reconfigurer les clients.
- Partitionnement côté client. Dans ce modèle, l’application cliente contient une logique (éventuellement sous la forme d’une bibliothèque) qui achemine les requêtes vers le serveur Redis approprié. Cette approche peut être utilisée avec Azure Cache pour Redis. Créez plusieurs caches Azure pour Redis (un pour chaque partition de données) et implémentez la logique côté client qui route les requêtes vers le cache approprié. Si le schéma de partitionnement change (si d’autres caches Azure pour Redis sont créés, par exemple), les applications clientes doivent peut-être être reconfigurées.
- Partitionnement assisté par proxy. Dans ce schéma, les applications clientes envoient des demandes à un service proxy intermédiaire qui comprend comment les données sont partitionnés, puis acheminent la requête vers le serveur Redis approprié. Cette approche peut également être utilisée avec Azure Cache pour Redis ; le service proxy peut être implémenté en tant que service cloud Azure. Cette approche nécessite un niveau de complexité supplémentaire pour implémenter le service, et les requêtes peuvent prendre plus de temps que d’utiliser le partitionnement côté client.
Le partitionnement de pages : comment fractionner des données entre plusieurs instances Redis sur le site web Redis fournit des informations supplémentaires sur l’implémentation du partitionnement avec Redis.
Implémenter des applications clientes du cache Redis
Redis prend en charge les applications clientes écrites dans de nombreux langages de programmation. Si vous générez de nouvelles applications à l’aide du .NET Framework, nous vous recommandons d’utiliser la bibliothèque cliente StackExchange.Redis. Cette bibliothèque fournit un modèle objet .NET Framework qui extrait les détails de la connexion à un serveur Redis, l’envoi de commandes et la réception de réponses. Il est disponible dans Visual Studio en tant que package NuGet. Vous pouvez utiliser cette même bibliothèque pour vous connecter à un cache Azure pour Redis ou un cache Redis personnalisé hébergé sur une machine virtuelle.
Pour vous connecter à un serveur Redis, vous utilisez la méthode statique Connect de la ConnectionMultiplexer classe. La connexion créée par cette méthode est créée pour une utilisation tout au long de la durée de vie de l’application cliente. La même connexion peut être utilisée par plusieurs threads simultanés. Ne reconnectez pas et déconnectez-vous chaque fois que vous effectuez une opération Redis, car cela peut dégrader les performances.
Vous pouvez spécifier les paramètres de connexion, tels que l’adresse de l’hôte Redis et le mot de passe. Si vous utilisez Azure Cache pour Redis, le mot de passe est la clé primaire ou secondaire générée pour Azure Cache pour Redis à l’aide du portail Azure.
Une fois connecté au serveur Redis, vous pouvez obtenir un handle sur la base de données Redis qui agit comme cache. La connexion Redis fournit la GetDatabase méthode pour effectuer cette opération. Vous pouvez ensuite récupérer des éléments à partir du cache et stocker des données dans le cache à l’aide des méthodes et StringGet des StringSet méthodes. Ces méthodes attendent une clé en tant que paramètre et retournent l’élément dans le cache qui a une valeur correspondante (StringGet) ou ajoutez l’élément au cache avec cette clé (StringSet).
Selon l’emplacement du serveur Redis, de nombreuses opérations peuvent entraîner une latence pendant qu’une requête est transmise au serveur et qu’une réponse est retournée au client. La bibliothèque StackExchange fournit des versions asynchrones de nombreuses méthodes qu’elle expose pour aider les applications clientes à rester réactives. Ces méthodes prennent en charge le modèle asynchrone basé sur des tâches dans le .NET Framework.
L’extrait de code suivant montre une méthode nommée RetrieveItem. Il illustre une implémentation du modèle cache-aside basé sur Redis et la bibliothèque StackExchange. La méthode prend une valeur de clé de chaîne et tente de récupérer l’élément correspondant à partir du cache Redis en appelant la StringGetAsync méthode (version asynchrone de StringGet).
Si l’élément est introuvable, il est extrait de la source de données sous-jacente à l’aide de la GetItemFromDataSourceAsync méthode (qui est une méthode locale et qui ne fait pas partie de la bibliothèque StackExchange). Elle est ensuite ajoutée au cache à l’aide de la StringSetAsync méthode afin qu’elle puisse être récupérée plus rapidement la prochaine fois.
// Connect to the Azure Redis cache
ConfigurationOptions config = new ConfigurationOptions();
config.EndPoints.Add("<your DNS name>.redis.cache.windows.net");
config.Password = "<Redis cache key from management portal>";
ConnectionMultiplexer redisHostConnection = ConnectionMultiplexer.Connect(config);
IDatabase cache = redisHostConnection.GetDatabase();
...
private async Task<string> RetrieveItem(string itemKey)
{
// Attempt to retrieve the item from the Redis cache
string itemValue = await cache.StringGetAsync(itemKey);
// If the value returned is null, the item was not found in the cache
// So retrieve the item from the data source and add it to the cache
if (itemValue == null)
{
itemValue = await GetItemFromDataSourceAsync(itemKey);
await cache.StringSetAsync(itemKey, itemValue);
}
// Return the item
return itemValue;
}
Les StringGet méthodes et StringSet les méthodes ne sont pas limitées à la récupération ou au stockage de valeurs de chaîne. Ils peuvent prendre n’importe quel élément sérialisé en tant que tableau d’octets. Si vous devez enregistrer un objet .NET, vous pouvez le sérialiser en tant que flux d’octets et utiliser la StringSet méthode pour l’écrire dans le cache.
De même, vous pouvez lire un objet à partir du cache à l’aide de la StringGet méthode et le désérialiser en tant qu’objet .NET. Le code suivant montre un ensemble de méthodes d’extension pour l’interface IDatabase (la GetDatabase méthode d’une connexion Redis retourne un IDatabase objet) et un exemple de code qui utilise ces méthodes pour lire et écrire un BlogPost objet dans le cache :
public static class RedisCacheExtensions
{
public static async Task<T> GetAsync<T>(this IDatabase cache, string key)
{
return Deserialize<T>(await cache.StringGetAsync(key));
}
public static async Task<object> GetAsync(this IDatabase cache, string key)
{
return Deserialize<object>(await cache.StringGetAsync(key));
}
public static async Task SetAsync(this IDatabase cache, string key, object value)
{
await cache.StringSetAsync(key, Serialize(value));
}
static byte[] Serialize(object o)
{
byte[] objectDataAsStream = null;
if (o != null)
{
var jsonString = JsonSerializer.Serialize(o);
objectDataAsStream = Encoding.ASCII.GetBytes(jsonString);
}
return objectDataAsStream;
}
static T Deserialize<T>(byte[] stream)
{
T result = default(T);
if (stream != null)
{
var jsonString = Encoding.ASCII.GetString(stream);
result = JsonSerializer.Deserialize<T>(jsonString);
}
return result;
}
}
Le code suivant illustre une méthode nommée RetrieveBlogPost qui utilise ces méthodes d’extension pour lire et écrire un objet sérialisable BlogPost dans le cache en suivant le modèle cache-aside :
// The BlogPost type
public class BlogPost
{
private HashSet<string> tags;
public BlogPost(int id, string title, int score, IEnumerable<string> tags)
{
this.Id = id;
this.Title = title;
this.Score = score;
this.tags = new HashSet<string>(tags);
}
public int Id { get; set; }
public string Title { get; set; }
public int Score { get; set; }
public ICollection<string> Tags => this.tags;
}
...
private async Task<BlogPost> RetrieveBlogPost(string blogPostKey)
{
BlogPost blogPost = await cache.GetAsync<BlogPost>(blogPostKey);
if (blogPost == null)
{
blogPost = await GetBlogPostFromDataSourceAsync(blogPostKey);
await cache.SetAsync(blogPostKey, blogPost);
}
return blogPost;
}
Redis prend en charge le pipeline de commandes si une application cliente envoie plusieurs requêtes asynchrones. Redis peut multiplexer les requêtes à l’aide de la même connexion plutôt que de recevoir et de répondre aux commandes dans une séquence stricte.
Cette approche permet de réduire la latence en rendant l’utilisation plus efficace du réseau. L’extrait de code suivant montre un exemple qui récupère les détails de deux clients simultanément. Le code envoie deux demandes, puis effectue un autre traitement (non affiché) avant d’attendre de recevoir les résultats. La Wait méthode de l’objet cache est similaire à la méthode .NET Framework Task.Wait :
ConnectionMultiplexer redisHostConnection = ...;
IDatabase cache = redisHostConnection.GetDatabase();
...
var task1 = cache.StringGetAsync("customer:1");
var task2 = cache.StringGetAsync("customer:2");
...
var customer1 = cache.Wait(task1);
var customer2 = cache.Wait(task2);
Pour plus d’informations sur l’écriture d’applications clientes qui peuvent utiliser le Cache Azure pour Redis, consultez la documentation azure Cache pour Redis. Des informations supplémentaires sont également disponibles sur StackExchange.Redis.
Les pipelines de page et les multiplexeurs sur le même site web fournissent plus d’informations sur les opérations asynchrones et le pipeline avec Redis et la bibliothèque StackExchange.
Utilisation de la mise en cache Redis
L’utilisation la plus simple de Redis pour la mise en cache concerne les paires clé-valeur où la valeur est une chaîne non interprétée de longueur arbitraire pouvant contenir des données binaires. (Il s’agit essentiellement d’un tableau d’octets qui peut être traité comme une chaîne). Ce scénario a été illustré dans la section Implémenter les applications clientes du Cache Redis plus haut dans cet article.
Les clés contiennent également des données non interprétées. Vous pouvez donc utiliser toutes les informations binaires comme clé. Plus la clé est toutefois longue, plus l’espace nécessaire est nécessaire pour stocker, et plus il faudra pour effectuer des opérations de recherche. Pour une facilité d’utilisation et une facilité de maintenance, concevez soigneusement votre espace de clés et utilisez des clés significatives (mais pas détaillées).
Par exemple, utilisez des clés structurées telles que « customer :100 » pour représenter la clé du client avec l’ID 100 plutôt que simplement « 100 ». Ce schéma vous permet de distinguer facilement les valeurs qui stockent différents types de données. Par exemple, vous pouvez également utiliser la clé « orders :100 » pour représenter la clé de l’ordre avec l’ID 100.
Outre les chaînes binaires unidimensionnelles, une valeur dans une paire clé-valeur Redis peut également contenir des informations plus structurées, notamment des listes, des ensembles (triés et non triés) et des hachages. Redis fournit un jeu de commandes complet qui peut manipuler ces types, et la plupart de ces commandes sont disponibles pour les applications .NET Framework via une bibliothèque cliente telle que StackExchange. La page Présentation des types de données et des abstractions Redis sur le site web Redis fournit une vue d’ensemble plus détaillée de ces types et des commandes que vous pouvez utiliser pour les manipuler.
Cette section récapitule certains cas d’usage courants pour ces types de données et commandes.
Effectuer des opérations atomiques et par lots
Redis prend en charge une série d’opérations get-and-set atomiques sur les valeurs de chaîne. Ces opérations éliminent les risques de concurrence potentiels susceptibles de survenir lorsque vous utilisez des commandes distinctes GET et SET. Les opérations disponibles sont les suivantes :
INCR, ,INCRBY,DECRetDECRBY, qui effectuent des opérations d’incrément atomique et de décrémentation sur des valeurs de données numériques entières. La bibliothèque StackExchange fournit des versions surchargées des méthodes etIDatabase.StringIncrementAsyncdesIDatabase.StringDecrementAsyncopérations pour effectuer ces opérations et retourner la valeur résultante stockée dans le cache. L’extrait de code suivant montre comment utiliser ces méthodes :ConnectionMultiplexer redisHostConnection = ...; IDatabase cache = redisHostConnection.GetDatabase(); ... await cache.StringSetAsync("data:counter", 99); ... long oldValue = await cache.StringIncrementAsync("data:counter"); // Increment by 1 (the default) // oldValue should be 100 long newValue = await cache.StringDecrementAsync("data:counter", 50); // Decrement by 50 // newValue should be 50GETSET, qui récupère la valeur associée à une clé et la remplace par une nouvelle valeur. La bibliothèque StackExchange rend cette opération disponible via laIDatabase.StringGetSetAsyncméthode. L’extrait de code suivant montre un exemple de cette méthode. Ce code retourne la valeur actuelle associée à la clé « data :counter » de l’exemple précédent. Ensuite, il réinitialise la valeur de cette clé à zéro, dans le cadre de la même opération :ConnectionMultiplexer redisHostConnection = ...; IDatabase cache = redisHostConnection.GetDatabase(); ... string oldValue = await cache.StringGetSetAsync("data:counter", 0);MGETetMSET, qui peuvent retourner ou modifier un ensemble de valeurs de chaîne en tant qu’opération unique. LesIDatabase.StringGetAsyncméthodes etIDatabase.StringSetAsyncles méthodes sont surchargées pour prendre en charge cette fonctionnalité, comme illustré dans l’exemple suivant :ConnectionMultiplexer redisHostConnection = ...; IDatabase cache = redisHostConnection.GetDatabase(); ... // Create a list of key-value pairs var keysAndValues = new List<KeyValuePair<RedisKey, RedisValue>>() { new KeyValuePair<RedisKey, RedisValue>("data:key1", "value1"), new KeyValuePair<RedisKey, RedisValue>("data:key99", "value2"), new KeyValuePair<RedisKey, RedisValue>("data:key322", "value3") }; // Store the list of key-value pairs in the cache cache.StringSet(keysAndValues.ToArray()); ... // Find all values that match a list of keys RedisKey[] keys = { "data:key1", "data:key99", "data:key322"}; // values should contain { "value1", "value2", "value3" } RedisValue[] values = cache.StringGet(keys);
Vous pouvez également combiner plusieurs opérations en une seule transaction Redis, comme décrit dans la section transactions et lots Redis plus haut dans cet article. La bibliothèque StackExchange prend en charge les transactions via l’interface ITransaction .
Vous créez un ITransaction objet à l’aide de la IDatabase.CreateTransaction méthode. Vous appelez des commandes à la transaction à l’aide des méthodes fournies par l’objet ITransaction .
L’interface ITransaction fournit l’accès à un ensemble de méthodes similaires à celles auxquelles l’interface IDatabase accède, sauf que toutes les méthodes sont asynchrones. Cela signifie qu’elles sont effectuées uniquement lorsque la ITransaction.Execute méthode est appelée. La valeur retournée par la ITransaction.Execute méthode indique si la transaction a été créée avec succès (true) ou si elle a échoué (false).
L’extrait de code suivant montre un exemple qui incrémente et décrémente deux compteurs dans le cadre de la même transaction :
ConnectionMultiplexer redisHostConnection = ...;
IDatabase cache = redisHostConnection.GetDatabase();
...
ITransaction transaction = cache.CreateTransaction();
var tx1 = transaction.StringIncrementAsync("data:counter1");
var tx2 = transaction.StringDecrementAsync("data:counter2");
bool result = transaction.Execute();
Console.WriteLine("Transaction {0}", result ? "succeeded" : "failed");
Console.WriteLine("Result of increment: {0}", tx1.Result);
Console.WriteLine("Result of decrement: {0}", tx2.Result);
N’oubliez pas que les transactions Redis sont différentes des transactions dans les bases de données relationnelles. La Execute méthode met simplement en file d’attente toutes les commandes qui composent la transaction à exécuter, et si l’une d’elles est incorrecte, la transaction est arrêtée. Si toutes les commandes ont été mises en file d’attente avec succès, chaque commande s’exécute de manière asynchrone.
Si une commande échoue, les autres continuent de traiter. Si vous devez vérifier qu’une commande s’est terminée correctement, vous devez extraire les résultats de la commande à l’aide de la propriété Result de la tâche correspondante, comme indiqué dans l’exemple précédent. La lecture de la propriété Result bloque le thread appelant jusqu’à ce que la tâche soit terminée.
Pour plus d’informations, consultez Transactions dans Redis.
Lorsque vous effectuez des opérations par lots, vous pouvez utiliser l’interface IBatch de la bibliothèque StackExchange. Cette interface permet d’accéder à un ensemble de méthodes similaires à celles accessibles par l’interface IDatabase , sauf que toutes les méthodes sont asynchrones.
Vous créez un IBatch objet à l’aide de la IDatabase.CreateBatch méthode, puis exécutez le lot à l’aide de la IBatch.Execute méthode, comme illustré dans l’exemple suivant. Ce code définit simplement une valeur de chaîne, incrémente et décrémente les mêmes compteurs utilisés dans l’exemple précédent et affiche les résultats :
ConnectionMultiplexer redisHostConnection = ...;
IDatabase cache = redisHostConnection.GetDatabase();
...
IBatch batch = cache.CreateBatch();
batch.StringSetAsync("data:key1", 11);
var t1 = batch.StringIncrementAsync("data:counter1");
var t2 = batch.StringDecrementAsync("data:counter2");
batch.Execute();
Console.WriteLine("{0}", t1.Result);
Console.WriteLine("{0}", t2.Result);
Il est important de comprendre que contrairement à une transaction, si une commande dans un lot échoue, car elle est incorrecte, les autres commandes peuvent toujours s’exécuter. La IBatch.Execute méthode ne retourne aucune indication de réussite ou d’échec.
Effectuer des opérations de déclenchement et d’oubli du cache
Redis prend en charge les opérations de déclenchement et d’oubli à l’aide d’indicateurs de commande. Dans ce cas, le client lance simplement une opération, mais n’a aucun intérêt dans le résultat et n’attend pas que la commande soit terminée. L’exemple suivant montre comment effectuer la commande INCR en tant qu’opération fire and forget :
ConnectionMultiplexer redisHostConnection = ...;
IDatabase cache = redisHostConnection.GetDatabase();
...
await cache.StringSetAsync("data:key1", 99);
...
cache.StringIncrement("data:key1", flags: CommandFlags.FireAndForget);
Spécifier automatiquement les clés arrivant à expiration
Lorsque vous stockez un élément dans un cache Redis, vous pouvez spécifier un délai d’expiration après lequel l’élément est automatiquement supprimé du cache. Vous pouvez également interroger combien de temps une clé a avant son expiration à l’aide de la TTL commande. Cette commande est disponible pour les applications StackExchange à l’aide de la IDatabase.KeyTimeToLive méthode.
L’extrait de code suivant montre comment définir un délai d’expiration de 20 secondes sur une clé et interroger la durée de vie restante de la clé :
ConnectionMultiplexer redisHostConnection = ...;
IDatabase cache = redisHostConnection.GetDatabase();
...
// Add a key with an expiration time of 20 seconds
await cache.StringSetAsync("data:key1", 99, TimeSpan.FromSeconds(20));
...
// Query how much time a key has left to live
// If the key has already expired, the KeyTimeToLive function returns a null
TimeSpan? expiry = cache.KeyTimeToLive("data:key1");
Vous pouvez également définir l’heure d’expiration sur une date et une heure spécifiques à l’aide de la commande EXPIRE, disponible dans la bibliothèque StackExchange comme KeyExpireAsync méthode :
ConnectionMultiplexer redisHostConnection = ...;
IDatabase cache = redisHostConnection.GetDatabase();
...
// Add a key with an expiration date of midnight on 1st January 2015
await cache.StringSetAsync("data:key1", 99);
await cache.KeyExpireAsync("data:key1",
new DateTime(2015, 1, 1, 0, 0, 0, DateTimeKind.Utc));
...
Tip
Vous pouvez supprimer manuellement un élément du cache à l’aide de la commande DEL, disponible via la bibliothèque StackExchange comme IDatabase.KeyDeleteAsync méthode.
Utiliser des balises pour mettre en corrélation croisée les éléments mis en cache
Un jeu Redis est une collection de plusieurs éléments qui partagent une seule clé. Vous pouvez créer un jeu à l’aide de la commande SADD. Vous pouvez récupérer les éléments d’un jeu à l’aide de la commande SMEMBERS. La bibliothèque StackExchange implémente la commande SADD avec la IDatabase.SetAddAsync méthode et la commande SMEMBERS avec la IDatabase.SetMembersAsync méthode.
Vous pouvez également combiner des ensembles existants pour créer de nouveaux ensembles à l’aide des commandes SDIFF (différence de jeu), SINTER (intersection set) et SUNION (set union). La bibliothèque StackExchange unifie ces opérations dans la IDatabase.SetCombineAsync méthode. Le premier paramètre de cette méthode spécifie l’opération set à effectuer.
Les extraits de code suivants montrent comment les jeux peuvent être utiles pour stocker et récupérer rapidement des collections d’éléments associés. Ce code utilise le BlogPost type décrit dans la section Implémenter les applications clientes du cache Redis plus haut dans cet article.
Un BlogPost objet contient quatre champs : un ID, un titre, un score de classement et une collection de balises. Le premier extrait de code montre les exemples de données utilisés pour remplir une liste d’objets BlogPost C# :
List<string[]> tags = new List<string[]>
{
new[] { "iot","csharp" },
new[] { "iot","azure","csharp" },
new[] { "csharp","git","big data" },
new[] { "iot","git","database" },
new[] { "database","git" },
new[] { "csharp","database" },
new[] { "iot" },
new[] { "iot","database","git" },
new[] { "azure","database","big data","git","csharp" },
new[] { "azure" }
};
List<BlogPost> posts = new List<BlogPost>();
int blogKey = 0;
int numberOfPosts = 20;
Random random = new Random();
for (int i = 0; i < numberOfPosts; i++)
{
blogKey++;
posts.Add(new BlogPost(
blogKey, // Blog post ID
string.Format(CultureInfo.InvariantCulture, "Blog Post #{0}",
blogKey), // Blog post title
random.Next(100, 10000), // Ranking score
tags[i % tags.Count])); // Tags--assigned from a collection
// in the tags list
}
Vous pouvez stocker les balises pour chaque BlogPost objet sous la forme d’un jeu dans un cache Redis et associer chaque jeu à l’ID du BlogPost. Cela permet à une application de trouver rapidement toutes les balises qui appartiennent à un billet de blog spécifique. Pour activer la recherche dans la direction opposée et rechercher tous les billets de blog qui partagent une balise spécifique, vous pouvez créer un autre ensemble qui contient les billets de blog référençant l’ID de balise dans la clé :
ConnectionMultiplexer redisHostConnection = ...;
IDatabase cache = redisHostConnection.GetDatabase();
...
// Tags are easily represented as Redis Sets
foreach (BlogPost post in posts)
{
string redisKey = string.Format(CultureInfo.InvariantCulture,
"blog:posts:{0}:tags", post.Id);
// Add tags to the blog post in Redis
await cache.SetAddAsync(
redisKey, post.Tags.Select(s => (RedisValue)s).ToArray());
// Now do the inverse so we can figure out which blog posts have a given tag
foreach (var tag in post.Tags)
{
await cache.SetAddAsync(string.Format(CultureInfo.InvariantCulture,
"tag:{0}:blog:posts", tag), post.Id);
}
}
Ces structures vous permettent d’effectuer de nombreuses requêtes courantes très efficacement. Par exemple, vous pouvez rechercher et afficher toutes les balises du billet de blog 1 comme suit :
// Show the tags for blog post #1
foreach (var value in await cache.SetMembersAsync("blog:posts:1:tags"))
{
Console.WriteLine(value);
}
Vous trouverez toutes les balises communes au billet de blog 1 et au billet de blog 2 en effectuant une opération d’intersection définie, comme suit :
// Show the tags in common for blog posts #1 and #2
foreach (var value in await cache.SetCombineAsync(SetOperation.Intersect, new RedisKey[]
{ "blog:posts:1:tags", "blog:posts:2:tags" }))
{
Console.WriteLine(value);
}
Et vous pouvez trouver tous les billets de blog qui contiennent une balise spécifique :
// Show the ids of the blog posts that have the tag "iot".
foreach (var value in await cache.SetMembersAsync("tag:iot:blog:posts"))
{
Console.WriteLine(value);
}
Rechercher des éléments récemment consultés
Une tâche courante requise pour de nombreuses applications consiste à trouver les éléments les plus récemment consultés. Par exemple, un site de blogs peut souhaiter afficher des informations sur les billets de blog les plus récemment lus.
Vous pouvez implémenter cette fonctionnalité à l’aide d’une liste Redis. Une liste Redis contient plusieurs éléments qui partagent la même clé. La liste agit comme une file d’attente à double fin. Vous pouvez envoyer des éléments vers l’une ou l’autre des extrémités de la liste à l’aide des commandes LPUSH (push gauche) et RPUSH (push droit). Vous pouvez récupérer des éléments à partir de la fin de la liste à l’aide des commandes LPOP et RPOP. Vous pouvez également retourner un ensemble d’éléments à l’aide des commandes LRANGE et RRANGE.
Les extraits de code suivants montrent comment effectuer ces opérations à l’aide de la bibliothèque StackExchange. Ce code utilise le BlogPost type des exemples précédents. Comme un billet de blog est lu par un utilisateur, la IDatabase.ListLeftPushAsync méthode envoie le titre du billet de blog sur une liste associée à la clé « blog :recent_posts » dans le cache Redis.
ConnectionMultiplexer redisHostConnection = ...;
IDatabase cache = redisHostConnection.GetDatabase();
...
string redisKey = "blog:recent_posts";
BlogPost blogPost = ...; // Reference to the blog post that has just been read
await cache.ListLeftPushAsync(
redisKey, blogPost.Title); // Push the blog post onto the list
Comme d’autres billets de blog sont lus, leurs titres sont poussés sur la même liste. La liste est triée par la séquence dans laquelle les titres sont ajoutés. Les billets de blog les plus récemment lus sont vers la fin gauche de la liste. (Si le même billet de blog est lu plusieurs fois, il a plusieurs entrées dans la liste.)
Vous pouvez afficher les titres des publications les plus récentes lues à l’aide de la IDatabase.ListRange méthode. Cette méthode prend la clé qui contient la liste, un point de départ et un point de fin. Le code suivant récupère les titres des 10 billets de blog (éléments de 0 à 9) à gauche de la liste :
// Show latest ten posts
foreach (string postTitle in await cache.ListRangeAsync(redisKey, 0, 9))
{
Console.WriteLine(postTitle);
}
La ListRangeAsync méthode ne supprime pas les éléments de la liste. Pour ce faire, vous pouvez utiliser les méthodes et IDatabase.ListLeftPopAsync les IDatabase.ListRightPopAsync méthodes.
Pour empêcher la liste de croître indéfiniment, vous pouvez découper régulièrement les éléments en supprimant la liste. L'extrait de code suivant vous montre comment supprimer tous les éléments sauf les cinq premiers de la liste.
await cache.ListTrimAsync(redisKey, 0, 5);
Implémenter un conseil d’administration
Par défaut, les éléments d’un ensemble ne sont pas conservés dans un ordre spécifique. Vous pouvez créer un jeu ordonné à l’aide de la commande ZADD (la IDatabase.SortedSetAdd méthode dans la bibliothèque StackExchange). Les éléments sont classés à l’aide d’une valeur numérique appelée score, qui est fournie en tant que paramètre à la commande.
L’extrait de code suivant ajoute le titre d’un billet de blog à une liste triée. Dans cet exemple, chaque billet de blog a également un champ de score qui contient le classement du billet de blog.
ConnectionMultiplexer redisHostConnection = ...;
IDatabase cache = redisHostConnection.GetDatabase();
...
string redisKey = "blog:post_rankings";
BlogPost blogPost = ...; // Reference to a blog post that has just been rated
await cache.SortedSetAddAsync(redisKey, blogPost.Title, blogPost.Score);
Vous pouvez récupérer les titres et les scores du billet de blog dans l’ordre croissant des scores à l’aide de la IDatabase.SortedSetRangeByRankWithScores méthode :
foreach (var post in await cache.SortedSetRangeByRankWithScoresAsync(redisKey))
{
Console.WriteLine(post);
}
Note
La bibliothèque StackExchange fournit également la IDatabase.SortedSetRangeByRankAsync méthode, qui retourne les données dans l’ordre de score, mais elle ne retourne pas les scores.
Vous pouvez également récupérer des éléments dans l’ordre décroissant des scores et limiter le nombre d’éléments retournés en fournissant des paramètres supplémentaires à la IDatabase.SortedSetRangeByRankWithScoresAsync méthode. L’exemple suivant affiche les titres et les scores des 10 billets de blog les plus classés :
foreach (var post in await cache.SortedSetRangeByRankWithScoresAsync(
redisKey, 0, 9, Order.Descending))
{
Console.WriteLine(post);
}
L’exemple suivant utilise la IDatabase.SortedSetRangeByScoreWithScoresAsync méthode, que vous pouvez utiliser pour limiter les éléments retournés à ceux qui se trouvent dans une plage de scores donnée :
// Blog posts with scores between 5000 and 100000
foreach (var post in await cache.SortedSetRangeByScoreWithScoresAsync(
redisKey, 5000, 100000))
{
Console.WriteLine(post);
}
Message à l’aide de canaux
En plus d’agir en tant que cache de données, un serveur Redis fournit la messagerie par le biais d’un mécanisme d’éditeur/d’abonné hautes performances. Les applications clientes peuvent s’abonner à un canal, et d’autres applications ou services peuvent publier des messages sur le canal. Les applications d’abonnement peuvent ensuite recevoir ces messages et les traiter.
Redis fournit la commande SUBSCRIBE pour les applications clientes à utiliser pour s’abonner aux canaux. Cette commande attend le nom d’un ou plusieurs canaux sur lesquels l’application accepte les messages. La bibliothèque StackExchange inclut l’interface ISubscription , qui permet à une application .NET Framework de s’abonner et de publier sur des canaux.
Vous créez un ISubscription objet à l’aide de la GetSubscriber méthode de connexion au serveur Redis. Ensuite, vous écoutez les messages sur un canal à l’aide de la SubscribeAsync méthode de cet objet. L’exemple de code suivant montre comment s’abonner à un canal nommé « messages :blogPosts » :
ConnectionMultiplexer redisHostConnection = ...;
ISubscriber subscriber = redisHostConnection.GetSubscriber();
...
await subscriber.SubscribeAsync("messages:blogPosts", (channel, message) => Console.WriteLine("Title is: {0}", message));
Le premier paramètre de la Subscribe méthode est le nom du canal. Ce nom suit les mêmes conventions que celles utilisées par les clés dans le cache. Le nom peut contenir toutes les données binaires, mais nous vous recommandons d’utiliser des chaînes relativement courtes et significatives pour garantir de bonnes performances et une facilité de maintenance.
Notez également que l’espace de noms utilisé par les canaux est distinct de celui utilisé par les clés. Cela signifie que vous pouvez avoir des canaux et des clés qui ont le même nom, bien que cela puisse rendre votre code d’application plus difficile à gérer.
Le deuxième paramètre est un délégué d’action. Ce délégué s’exécute de manière asynchrone chaque fois qu’un nouveau message apparaît sur le canal. Cet exemple affiche simplement le message sur la console (le message contiendra le titre d’un billet de blog).
Pour publier sur un canal, une application peut utiliser la commande Redis PUBLISH. La bibliothèque StackExchange fournit la IServer.PublishAsync méthode permettant d’effectuer cette opération. L’extrait de code suivant montre comment publier un message sur le canal « messages :blogPosts » :
ConnectionMultiplexer redisHostConnection = ...;
ISubscriber subscriber = redisHostConnection.GetSubscriber();
...
BlogPost blogPost = ...;
subscriber.PublishAsync("messages:blogPosts", blogPost.Title);
Vous devez comprendre plusieurs points sur le mécanisme de publication/abonnement :
- Plusieurs abonnés peuvent s’abonner au même canal, et ils recevront tous les messages publiés sur ce canal.
- Les abonnés reçoivent uniquement les messages publiés après leur abonnement. Les canaux ne sont pas mis en mémoire tampon et une fois qu’un message est publié, l’infrastructure Redis envoie le message à chaque abonné, puis la supprime.
- Par défaut, les messages sont reçus par les abonnés dans l’ordre dans lequel ils sont envoyés. Dans un système hautement actif avec un grand nombre de messages et de nombreux abonnés et éditeurs, la remise séquentielle de messages garantie peut ralentir les performances du système. Si chaque message est indépendant et que l’ordre n’est pas important, vous pouvez activer le traitement simultané par le système Redis, ce qui peut contribuer à améliorer la réactivité. Pour ce faire, vous pouvez effectuer cette opération dans un client StackExchange en définissant preserveAsyncOrder de la connexion utilisée par l’abonné sur false :
ConnectionMultiplexer redisHostConnection = ...;
redisHostConnection.PreserveAsyncOrder = false;
ISubscriber subscriber = redisHostConnection.GetSubscriber();
Considérations relatives à la sérialisation
Lorsque vous choisissez un format de sérialisation, prenez en compte les compromis entre les performances, l’interopérabilité, le contrôle de version, la compatibilité avec les systèmes existants, la compression des données et la surcharge de mémoire. Lorsque vous évaluez les performances, n’oubliez pas que les benchmarks dépendent fortement du contexte. Ils peuvent ne pas refléter votre charge de travail réelle et ne pas prendre en compte les bibliothèques ou versions plus récentes. Il n’existe aucun sérialiseur « le plus rapide » unique pour tous les scénarios.
Certaines options à prendre en compte sont :
Les mémoires tampons de protocole (également appelées protobuf) sont un format de sérialisation développé par Google pour sérialiser efficacement les données structurées. Il utilise des fichiers de définition fortement typés pour définir des structures de message. Ces fichiers de définition sont ensuite compilés en code spécifique au langage pour sérialiser et désérialiser les messages. Protobuf peut être utilisé via des mécanismes RPC existants, ou il peut générer un service RPC.
Apache Thrift utilise une approche similaire, avec des fichiers de définition fortement typés et une étape de compilation pour générer le code de sérialisation et les services RPC.
Apache Avro fournit des fonctionnalités similaires aux mémoires tampons de protocole et Thrift, mais il n’existe aucune étape de compilation. Au lieu de cela, les données sérialisées incluent toujours un schéma qui décrit la structure.
JSON est une norme ouverte qui utilise des champs de texte lisibles par l’homme. Il offre une large prise en charge multiplateforme. JSON n’utilise pas de schémas de message. Étant un format textuel, il n’est pas très efficace sur le fil. Dans certains cas, toutefois, vous pouvez retourner des éléments mis en cache directement à un client via HTTP, auquel cas le stockage json peut économiser le coût de désérialisation à partir d’un autre format, puis sérialiser vers JSON.
binary JSON (BSON) est un format de sérialisation binaire qui utilise une structure similaire à JSON. BSON a été conçu pour être léger, facile à analyser et à sérialiser et désérialiser rapidement, par rapport à JSON. Les charges utiles sont comparables en taille au format JSON. Selon les données, une charge utile BSON peut être plus petite ou supérieure à une charge utile JSON. BSON a des types de données supplémentaires qui ne sont pas disponibles dans JSON, notamment BinData (pour les tableaux d’octets) et Date.
MessagePack est un format de sérialisation binaire conçu pour être compact pour la transmission sur le fil. Il ne comporte aucun schéma de message ni contrôle du type de message.
Bond est une infrastructure multiplateforme permettant d’utiliser des données schématisées. Il prend en charge la sérialisation et la désérialisation inter-langues. Les différences notables d’autres systèmes répertoriés ici sont la prise en charge de l’héritage, des alias de type et des génériques.
gRPC est un système RPC open source développé par Google. Par défaut, il utilise les mémoires tampons de protocole comme langage de définition et format d’échange de messages sous-jacents.
Étapes suivantes
- Documentation Azure Cache pour Redis
- FAQ sur Azure Cache pour Redis
- Modèle asynchrone basé sur des tâches
- Documentation Redis
- StackExchange.Redis
- Guide de partitionnement des données
Ressources associées
Les modèles suivants peuvent également être pertinents pour votre scénario lorsque vous implémentez la mise en cache dans vos applications :
Modèle cache-aside : ce modèle décrit comment charger des données à la demande dans un cache à partir d’un magasin de données. Ce modèle permet également de maintenir la cohérence entre les données conservées dans le cache et les données du magasin de données d’origine.
Le modèle de partitionnement fournit des informations sur l’implémentation du partitionnement horizontal pour améliorer la scalabilité lors du stockage et de l’accès à de grands volumes de données.