2010-10-28 3 views
2

Je voudrais demander votre avis d'expert sur une architecture réalisable en C#.C# conseils d'architecture: méthode pour mettre en cache des données dans une structure?

J'ai un service C# qui répond à une requête d'un utilisateur local sur le réseau local, récupère des paquets de données provenant d'Internet, et croque ces données pour produire des tableaux de données dans une structure. Chaque requête de données prend environ 2 secondes et renvoie 4000 octets. Il pourrait y avoir des dizaines de milliers de demandes par jour. Pour accélérer le tout et réduire la bande passante, j'ai besoin de mettre en cache les résultats de l'analyse des données de sorte que les deuxièmes et ultérieurs accès soient servis instantanément aux autres utilisateurs du réseau local (il pourrait y avoir> 50 utilisateurs).

Contraintes:

  1. Les données sous-jacentes ne change jamais, à savoir que je n'ont pas à vous soucier des données « sales » (super!).
  2. Les données que je veux mettre en cache sont une structure assez complexe, contenant des tableaux imbriqués de DateTime, doubles, etc. Les données sont croquées, en utilisant beaucoup de maths, à partir des données provenant d'Internet.
  3. Je ne peux pas utiliser plus de 100 Mo de mémoire, quelle que soit la quantité de données mises en cache (c'est-à-dire que le cache doit être limité en taille).
  4. Je ne peux pas indexer les données dans le cache par un index numérique, je dois l'indexer avec une combinaison de date ("AAAA-MM-JJ") et une chaîne d'identification unique ("XXXXXXXX").
  5. Il doit être rapide, c'est-à-dire qu'il doit servir la plupart de ses réponses à partir de la RAM.
  6. Les données dans le cache doivent être conservées sur le disque toutes les 24 heures.

Voici mes options au moment:

  1. Cache les données dans la classe du serveur, en utilisant des variables privées (par exemple de liste privée ou un dictionnaire), sérialisent puis sur disque de temps en temps;
  2. Utiliser une base de données;

Votre opinion d'expert m'intéresse.

Répondre

2

De loin la solution la plus simple est d'utiliser un Dictionary<string, ComplexDataStructure> pour cela.

En ce qui concerne vos besoins:

  1. vie du cache est plus facile à gérer en ayant un fil d'arrière-plan qui fait une analyse du cache jamais 10 minutes ou les heures.Avec le ComplexDataStructure, vous stockez un DateTime lorsque le cache a été créé et retirer la clé du dictionnaire une fois sa durée de vie a expiré;

  2. Parce que vous stockez la structure de données réelles, la complexité est pas un problème;

  3. Limitation de la taille peut être difficile. sizeof() equivalent for reference types? peut vous aider à calculer la taille de la structure de l'objet. Cette opération ne sera pas triviale, mais vous pouvez stocker le résultat avec ComplexDataStructure. Ensuite, le même thread que celui utilisé pour 1. peut supprimer des entrées lorsque vous manquez d'espace. Une solution plus simple serait probablement d'utiliser GC.GetTotalMemory() et de déterminer si l'utilisation totale de la mémoire de votre processus est en dehors d'une limite spécifique. Ensuite, il suffit de supprimer un élément de cache et lors de la seconde exécution, lorsque vous constatez que vous utilisez encore trop de mémoire, supprimez-en un second;

  4. Il suffit d'utiliser une chaîne;

  5. Utilisation du Dictionary<,> est probablement de la façon dont la graisse jeûné;

  6. Encore une fois, utiliser le fil de 1. et mettre en œuvre une telle logique. Assurez-vous de gérer correctement votre stratégie de verrouillage. Le plus gros problème ici sera que vous ne voulez pas le craquement lorsqu'un thread différent est déjà en train de croquer les données.Une solution à cela pourrait être la stratégie suivante:

    1. Verrouiller le dictionnaire;

    2. Vérifiez si l'élément de cache existe;

    3. Lorsque l'élément de cache n'existe pas:

      1. Créer un élément de cache vide;

      2. Ajouter cela au dictionnaire;

      3. Mettez un verrou sur l'élément de cache;

      4. Libérer le verrou sur le dictionnaire;

      5. Faire le calcul de données;

      6. Ajoutez les données croquées à l'élément de cache; Relâchez le verrou sur l'élément de cache;

    4. Lorsque l'élément de cache existe déjà; Lorsque l'élément de cache contient réellement les données croquées, renvoyez-le; Lorsque l'élément de cache ne contient pas les données croquées, placez un verrou sur l'élément de cache;

    5. A l'intérieur du verrou, les données croisées seront apparues (car le verrou vous oblige à attendre sur l'autre thread).

Il y a d'autres questions qui devront être résolues, mais je pense que les bases sont décrites ici.

+0

Bonne réponse, merci. Plutôt que de l'implémenter moi-même, j'ai fini par utiliser une solution prête à l'emploi, la bibliothèque de mise en cache .NET de Kellerman. – Contango

+0

De rien. –

0

Qu'en est-il de: Utiliser les méthodes internes fournies par IIS?

+0

Désolé, ma question n'était pas assez claire: je dois mettre en cache des données locales, contenues dans une structure d'une classe de service écrite en C#. J'ai tranché la question pour que ce soit plus clair. – Contango

0

Je pense avoir trouvé la solution parfaite: la bibliothèque de journalisation PostSharp + Kellerman .NET. PostSharp nécessite une légère courbe d'apprentissage (environ 15 minutes), mais une fois que vous êtes opérationnel, vous pouvez annoter votre méthode avec l'attribut [Cachable], et le système mettra automatiquement en cache les résultats de cette méthode pour vous. Il s'agit d'une solution aussi propre que possible.

Questions connexes