39 votes

ServiceStack.Net Redis: Stockage d'objets associés vs ID d'objets associés

Mon équipe a décidé de travailler avec Redis via le ServiceStack.net Redis Client comme un référentiel sous-jacent pour un nouveau haut-le volume de site web, nous travaillons sur. Je ne suis pas vraiment sûr de savoir où chercher de la documentation pour cette question (soit en général Redis docs ou spécifiques ServiceStack.Net docs ou les deux) - est-il réellement une source de référence pour la documentation sur la façon de mettre en œuvre un Redis via ServiceStack.Net qui comprend tout ce que vous devez savoir à propos de ces deux concepts et Redis ServiceStack.Net concepts, ou devons-nous intégrer la documentation de ces deux aspects séparément pour obtenir l'image complète?.

Je suis juste aux prises avec exactement comment stocker des objets liés à notre modèle d'objet graphique. Voici un scénario simple que je veux travailler avec:

Il y a deux objets dans le système: User et Feed. En SGBDR termes de ces deux objets ont un un-à-plusieurs relations, c'est un User a une collection d' Feed objets et une source d'alimentation ne peut appartenir qu'à un User. Les flux seront toujours accessibles à partir de Redis par l'intermédiaire de leur utilisateur mais de temps en temps, nous voulons obtenir l'accès à l'utilisateur par l'intermédiaire d'un flux d'instance.

Donc la question que je me pose est de savoir si nous devrions stocker les objets associés à des propriétés ou doit-on stocker l' Id des valeurs des objets? Pour illustrer:

À L'Approche D'Un:

public class User
{
    public User()
    {
        Feeds = new List<Feed>();
    }

    public int Id { get; set; }

    public List<Feed> Feeds { get; set; }

    // Other properties
}

public class Feed
{
    public long Id { get; set; }

    public User User { get; set; }
}

Approche B:

public class User
{
    public User()
    {
        FeedIds = new List<long>();
    }

    public long Id { get; set; }

    public List<long> FeedIds { get; set; } 

    public List<Feed> GetFeeds()
    {
        return repository.GetFeeds( FeedIds );
    }
}

public class Feed
{
    public long Id { get; set; }

    public long UserId { get; set; }

    public User GetUser()
    {
        return repository.GetUser( UserId );
    }
}

Laquelle des méthodes ci-dessus fonctionne le mieux? J'ai vu les deux approches utilisées dans divers exemples, mais j'ai l'impression que certains des exemples que j'ai vu peut-être pas les meilleures pratiques.

Quelques simples questions connexes:

  • Si je fais une modification à un objet il sera automatiquement répercutée dans le Redis, ou aurez-vous besoin d'une sauvegarde? Je suis en supposant que le dernier, mais ont besoin d'être absolument clair.
  • Si je peux utiliser Une Approche, une mise à jour à l'Utilisateur de l'objet X est reflété à travers l'ensemble de l'objet graphique où il est référencé ou est-il nécessaire d'enregistrer les modifications dans le graphique?
  • Est-il un problème avec le stockage d'un objet via son interface (c'est à dire utiliser IList<Feed> plutôt List<Feed>?

Désolé si ces questions sont un peu de base - jusqu'à il y a 2 semaines, je n'avais même jamais entendu parler de Redis - le laisser seul ServiceStack - (ni avait personne dans mon équipe), de sorte que nous sommes vraiment commencer à partir de zéro ici...

66voto

mythz Points 54874

Plutôt que de re-hachage beaucoup d'autres de la documentation qui existe dans la nature, je vais énumérer quelques autour de quelques informations de fond autour de Redis + ServiceStack le Redis Client:

Il n'y a pas de magie - Redis est une toile vierge

Tout d'abord je tiens à souligner que l'utilisation de Redis comme une banque de données fournit une toile vierge et n'a pas de concept d'entités liées par lui-même. c'est à dire qu'il offre seulement l'accès à l'distribué comp-sci structures de données. Comment les relations sont stockés est finalement le pilote client (c'est à dire ServiceStack C# Redis Client) ou le développeur de l'application, par l'utilisation de Redis primitive de la structure de données des opérations. Depuis toutes les principales structures de données sont mis en œuvre dans le Redis, en gros, vous avez une totale liberté sur la façon dont vous voulez structurer et stocker vos données.

Pensez à comment vous vous la structure des relations dans le code

Donc, la meilleure façon de penser sur la façon de stocker des trucs dans le Redis, est complètement mépris sur la façon dont les données sont stockées dans une table de SGBDR et de réfléchir à la façon dont elle est stockée dans votre code, c'est à dire en utilisant le construit en C# les classes de collection dans la mémoire - Redis miroirs de comportement avec leurs données côté serveur-structures.

En dépit de ne pas avoir un concept d'entités liées, Redis intégré dans l' Ensemble et SortedSet structures de données fournissent le moyen idéal pour stocker les index. E. g. Redis de l' Ensemble de la collection ne stocke un maximum de 1 survenance d'un élément. Cela signifie que vous pouvez ajouter des éléments/keys/ids et pas de soins si l'élément existe déjà en tant que le résultat final sera le même si vous l'avez appelé 1 ou 100 fois - c'est à dire qu'il est idempotent, et, finalement, seulement 1 élément est stocké dans le Jeu. Ainsi, une commune de cas d'utilisation, c'est quand le stockage d'un objet graphique (l'ensemble de la racine) est de stocker l'Id de l'Entité Enfant (aka Clés Étrangères) dans un Ensemble à chaque fois que vous enregistrez le modèle.

La visualisation de vos données

Pour une bonne visualisation de la façon dont les Entités sont stockées dans le Redis, je vous recommandons d'installer le Redis Administrateur de l'INTERFACE utilisateur , qui fonctionne bien, avec ServiceStack C# Redis Client, car il utilise la clé convention de nommage ci-dessous pour fournir une belle vue hiérarchique, le regroupement de vos tapé entités ensemble (malgré toutes les clés existantes dans le même espace).

Pour afficher et modifier une Entité, cliquez sur Modifier le lien pour voir et modifier l'entité sélectionnée interne de représentation JSON. Nous espérons que vous serez en mesure de prendre de meilleures décisions au sujet de la conception de vos modèles une fois que vous pouvez voir comment ils sont stockés.

Comment POCO / Entités sont stockées

Le C# Redis Client fonctionne avec n'importe quel POCOs qui ont une clé primaire unique - qui, par défaut, devrait être Id (bien que cette convention substituables avec ModelConfig). Essentiellement POCOs est stocké dans le Redis comme JSON sérialisé avec à la fois l' typeof(Poco).Name et de la Id utilisé pour former une clé unique pour cette instance. E. g:

urn:Poco:{Id} => '{"Id":1,"Foo":"Bar"}'

POCOs dans le C# Client sont classiquement sérialisée en utilisant ServiceStack rapide Sérialiseur Json où seuls les biens publics que les accesseurs sont sérialisés (et les organismes de normalisation pour obtenir de sérialisé en arrière).

Les valeurs par défaut sont remplacable avec [DataMember] attrs, mais pas recommandé, car il uglifies votre POCOs.

Les entités sont blobbed

Donc, sachant que POCOs dans le Redis sont juste blobbed, vous ne voulez tenir les non-racine d'agrégat de données sur votre POCOs que les propriétés publiques (sauf si vous voulez délibérément pour stocker des données redondantes). Une bonne convention est d'utiliser des méthodes pour récupérer les données associées (car il n'en sérialisé), mais indique également à votre application les méthodes qui font des appels à distance à lire les données.

Donc, la question de savoir si l' Alimentation doit obtenir stockées avec l' Utilisateur est de savoir si ou non il est non-racine d'agrégat de données, c'est à dire si oui ou non vous voulez accéder aux flux en dehors du contexte de l'utilisateur? Si non, alors laissez l' List<Feed> Feeds de la propriété sur l' User type.

Le Maintien Des Index Personnalisés

Toutefois, si vous souhaitez garder tous les aliments de la accessibles de façon indépendante, c'est à dire avec redisFeeds.GetById(1) alors vous voulez entreposer à l'extérieur de l'utilisateur et de maintenir un indice de relier les 2 entités.

Comme vous l'avez remarqué il y a plusieurs façons de stocker des relations entre les entités et la façon dont vous le faire est en grande partie une question de préférence. Pour l'entité enfant à un parent>enfant de relation vous voulez toujours stocker les ParentId avec l'enfant de l'entité. Pour le Parent, vous pouvez choisir de stocker une collection de ChildIds avec le modèle, puis de faire un seul aller chercher de tous les enfants afin de réhydrater le modèle.

Une autre façon est de maintenir l'indice à l'extérieur de la maison mère dto dans son propre Jeu pour chaque instance parent. Quelques bons exemples de ce qui est dans le code Source C# de le Redis StackOverflow démo où la relation de l' Users > Questions et Users > Answers se trouve dans:

idx:user>q:{UserId} => [{QuestionId1},{QuestionId2},etc]
idx:user>a:{UserId} => [{AnswerId1},{AnswerId2},etc]

Bien que le C# RedisClient ne prend en charge par défaut Parent/Enfant, la convention par l'intermédiaire de son TParent.StoreRelatedEntities(), TParent.GetRelatedEntities<TChild>() et TParent.DeleteRelatedEntities() Api lorsqu'un index est maintenu derrière la scène qui ressemble à:

ref:Question/Answer:{QuestionId} => [{answerIds},..]

Effectivement ce sont juste certaines de vos options possibles, où il y a beaucoup de façons différentes pour atteindre le même but et dans lequel vous avez également la liberté de faire vos propres.

NoSQL du schéma, lâche-typage des libertés fondamentales devrait être adopté et vous ne devriez pas être inquiet au sujet d'essayer de suivre un rigide, structure prédéfinie vous connaissez peut-être lors de l'utilisation d'un SGBDR.

En conclusion, il n'y a pas de bonne façon de stocker les données dans le Redis, par exemple, Le C# Redis Client fait quelques hypothèses afin de fournir une API de haut niveau autour de Poco et il blobs la POCOs dans le Redis binaire-sûr les valeurs de chaîne - même si il y a d'autres clients préfèrent stocker des entités propriétés dans le Redis Hachages (Dictionnaires) à la place. Les deux fonctionneront.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X