Aller au contenu principal

Le cache distribué en .NET

· 4 minutes de lecture

Le cache est l'un des moyens les plus efficaces d'améliorer les performances d'une application.
La plupart des applications .NET débutent avec un simple cache en mémoire utilisant MemoryCache ou IMemoryCache. Cela fonctionne parfaitement lorsque l'application s'exécute sur un seul serveur.

Cependant, les applications modernes s'exécutent rarement sur une seule machine.

Lorsque les applications montent en charge horizontalement sur plusieurs instances, le cache en mémoire cesse de fonctionner de façon fiable. Chaque instance maintient son propre cache, ce qui signifie que l'état applicatif devient incohérent à l'échelle du cluster.

C'est ici que le cache distribué devient essentiel.


Cache distribué


Le problème des caches en mémoire

Considérez une application ASP.NET typique déployée derrière un load balancer.

          Load Balancer
|
---------------------------
| | |
Server A Server B Server C

Chaque serveur possède son propre cache en mémoire.

Si une requête met à jour des données en cache sur le serveur A, les caches des serveurs B et C restent périmés.

Cela entraîne plusieurs problèmes :

  • un état applicatif incohérent
  • des entrées de cache périmées
  • des préchauffages de cache dupliqués
  • un comportement imprévisible

Pour résoudre ce problème, le cache doit être partagé entre tous les nœuds.


Qu'est-ce qu'un cache distribué ?

Un cache distribué est un cache centralisé ou en cluster accessible par plusieurs instances applicatives.

Au lieu de stocker les données en cache dans le processus de l'application, les données sont stockées dans un store clé-valeur distribué.

           Application Nodes

App A App B App C
| | |
+---------+---------+
|
Distributed Cache

Tous les nœuds applicatifs lisent et écrivent les entrées de cache depuis le même store distribué.

Cela garantit :

  • des données en cache cohérentes
  • un état applicatif partagé
  • une meilleure évolutivité

Exemple de base d'un cache distribué en .NET

Un cache distribué s'utilise généralement via une abstraction telle que IDistributedCache.

Exemple :

public class ProductService
{
private readonly IDistributedCache _cache;

public ProductService(IDistributedCache cache)
{
_cache = cache;
}

public async Task<string?> GetProductAsync(string id)
{
var cached = await _cache.GetStringAsync(id);

if (cached != null)
return cached;

var product = await LoadProductFromDatabase(id);

await _cache.SetStringAsync(id, product);

return product;
}

private Task<string> LoadProductFromDatabase(string id)
{
return Task.FromResult($"Product {id}");
}
}

L'application vérifie d'abord le cache. Si la valeur est absente, la donnée est chargée depuis la base de données, puis stockée dans le cache.

Ce modèle est appelé cache-aside.


Solutions courantes de cache distribué

Plusieurs technologies offrent des capacités de cache distribué.

Redis​

Redis est l'un des caches distribués les plus utilisés.

Il offre :

  • un stockage clé-valeur
  • de hautes performances
  • des opérations en mémoire

Cependant, Redis nécessite souvent des composants supplémentaires lorsqu'il est utilisé pour la coordination distribuée.


Caches adossés à une base de données​

Certaines applications utilisent des bases de données relationnelles comme caches.

Bien que simple, cette approche introduit :

  • de la contention sur la base de données
  • des performances réduites
  • une évolutivité limitée

Plateformes clé-valeur distribuées​

Les systèmes distribués modernes utilisent souvent des plateformes clé-valeur distribuées qui offrent à la fois des primitives de cache et de coordination.

Ces systèmes prennent en charge :

  • le cache distribué
  • les verrous distribués
  • l'élection de leader
  • les notifications de changement
  • la coordination de cluster

Utiliser Clustron comme cache distribué

Clustron fournit une plateforme clé-valeur distribuée conçue pour les applications .NET.

Parce qu'elle s'exécute en tant que cluster distribué, toutes les instances applicatives interagissent avec le même store de données partagé.

Exemple :

using Clustron.DKV.Client;

var client = await DKVClient.InitializeRemote(
"teststore",
new[]
{
new DkvServerInfo("localhost", 7861)
});

await client.PutAsync("product:1", "Laptop");

var value = await client.GetAsync<string>("product:1");

Console.WriteLine(value);

Dans cet exemple :

  • les nœuds applicatifs se connectent au cluster
  • les données sont stockées dans le store distribué
  • tous les nœuds voient les mêmes données

Cela permet au cache de rester cohérent sur l'ensemble du cluster.


Quand utiliser le cache distribué

Le cache distribué est particulièrement utile dans les systèmes qui :

  • exécutent plusieurs instances applicatives
  • traitent de gros volumes de requêtes
  • s'appuient fortement sur des lectures en base de données
  • requièrent un état applicatif partagé

Les cas d'usage typiques incluent :

  • les applications web ASP.NET
  • les architectures microservices
  • les systèmes de traitement d'arrière-plan
  • les plateformes d'API

Résumé

Le cache en mémoire fonctionne bien pour les applications mono-serveur, mais les systèmes distribués modernes exigent une couche de cache partagée.

Le cache distribué permet à plusieurs instances applicatives de partager les mêmes données en cache, améliorant l'évolutivité et la cohérence.

Des plateformes telles que Clustron fournissent un store clé-valeur distribué qui facilite l'implémentation du cache distribué et de la coordination dans les applications .NET.