Redis
 sql >> Database >  >> NoSQL >> Redis

ServiceStack.Net Redis:archiviazione di oggetti correlati rispetto a ID oggetto correlati

Piuttosto che eseguire nuovamente l'hash di molta altra documentazione che è là fuori in natura, ne elencherò un paio in giro per alcune informazioni di base sul client Redis di Redis + ServiceStack:

  • Cosa pensare durante la progettazione di un'applicazione Redis NoSQL
  • Progettazione di un database NoSQL utilizzando Redis
  • Panoramica generale di Redis e .NET
  • Versioni senza schemi e migrazioni dei dati con il client Redis C#

Non c'è magia:Redis è una tela bianca

Innanzitutto voglio sottolineare che l'utilizzo di Redis come archivio dati fornisce solo una tela vuota e non ha alcun concetto di entità correlate di per sé. ovvero fornisce solo l'accesso alle strutture di dati comp-sci distribuite. Il modo in cui le relazioni vengono archiviate dipende in definitiva dal driver del client (ad esempio ServiceStack C# Redis Client) o dallo sviluppatore dell'app, utilizzando le operazioni della struttura dati primitiva di Redis. Poiché tutte le principali strutture di dati sono implementate in Redis, in pratica hai la completa libertà su come strutturare e archiviare i tuoi dati.

Pensa a come strutturare le relazioni nel codice

Quindi il modo migliore per pensare a come archiviare elementi in Redis è ignorare completamente il modo in cui i dati vengono archiviati in una tabella RDBMS e pensare a come vengono archiviati nel codice, ovvero utilizzando le classi di raccolta C# integrate in memoria - che Redis rispecchia nel comportamento con le sue strutture di dati lato server.

Nonostante non abbia un concetto di entità correlate, il Set integrato di Redis e SortedSet le strutture dati forniscono il modo ideale per archiviare gli indici. Per esempio. Set di Redis collection memorizza solo un massimo di 1 occorrenza di un elemento. Ciò significa che puoi aggiungere in sicurezza elementi/chiavi/ID ad esso e non preoccuparti se l'elemento esiste già poiché il risultato finale sarà lo stesso se lo avessi chiamato 1 o 100 volte, ovvero è idempotente e alla fine solo 1 elemento rimane memorizzato in il set. Quindi un caso d'uso comune è quando si archivia un grafico oggetto (radice aggregata) è archiviare gli ID entità figlio (aka chiavi esterne) in un insieme ogni volta che si salva il modello.

Visualizzare i tuoi dati

Per una buona visualizzazione di come le entità sono archiviate in Redis, consiglio di installare l'interfaccia utente di amministrazione Redis che funziona bene con il client Redis C# di ServiceStack poiché utilizza la convenzione di denominazione delle chiavi di seguito per fornire una bella visualizzazione gerarchica, raggruppando le entità digitate insieme (nonostante tutte le chiavi esistenti nello stesso spazio delle chiavi globale).

Per visualizzare e modificare un'entità, fai clic su Modifica collegamento per visualizzare e modificare la rappresentazione JSON interna dell'entità selezionata. Spero che tu possa prendere decisioni migliori su come progettare i tuoi modelli una volta che avrai visto come sono archiviati.

Come vengono archiviati POCO / Entità

Il client C# Redis funziona con qualsiasi POCO che abbia una singola chiave primaria, che per impostazione predefinita dovrebbe essere Id (sebbene questa convenzione sia sovrascrivibile con ModelConfig). Essenzialmente i POCO vengono archiviati in Redis come JSON serializzato con entrambi typeof(Poco).Name e l'Id utilizzato per formare una chiave univoca per quell'istanza. Es:

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

I POCO nel client C# vengono serializzati convenzionalmente usando il serializzatore Json veloce di ServiceStack in cui vengono serializzate solo le proprietà con getter pubblici (e i setter pubblici vengono deserializzati).

I valori predefiniti possono essere ignorati con [DataMember] attrs ma non consigliato poiché sminuisce i tuoi POCO.

Le entità sono blob

Quindi, sapendo che i POCO in Redis sono solo blob, vuoi solo mantenere i dati root non aggregati sui tuoi POCO come proprietà pubbliche (a meno che tu non voglia intenzionalmente archiviare dati ridondanti). Una buona convenzione consiste nell'usare metodi per recuperare i dati correlati (poiché non verranno serializzati), ma indica anche alla tua app quali metodi effettuano chiamate remote per leggere i dati.

Quindi la domanda se il Feed dovrebbe essere archiviato con l'Utente è se si tratta o meno di dati radice non aggregati, ovvero se si desidera o meno accedere ai feed degli utenti al di fuori del contesto dell'utente? In caso negativo, lascia l'List<Feed> Feeds proprietà sull'User digitare.

Mantenimento degli indici personalizzati

Se invece desideri mantenere tutti i feed accessibili in modo indipendente, ad esempio con redisFeeds.GetById(1) quindi vorrai archiviarlo all'esterno dell'utente e mantenere un indice che collega le 2 entità.

Come hai notato, ci sono molti modi per archiviare le relazioni tra entità e il modo in cui lo fai è in gran parte una questione di preferenza. Per l'entità figlio in un genitore>figlio vorresti sempre memorizzare il ParentId con l'entità figlio. Per il genitore puoi scegliere di archiviare una raccolta di ChildIds con il modello e quindi eseguire un unico recupero per tutte le entità figlio per reidratare il modello.

Un altro modo è mantenere l'indice al di fuori del dto padre nel proprio Set per ogni istanza padre. Alcuni buoni esempi di ciò si trovano nel codice sorgente C# della demo Redis StackOverflow in cui la relazione di Users > Questions e Users > Answers è memorizzato in:

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

Sebbene C# RedisClient includa il supporto per una convenzione padre/figlio predefinita tramite TParent.StoreRelatedEntities(), TParent.GetRelatedEntities<TChild>() e TParent.DeleteRelatedEntities() API in cui viene mantenuto un indice dietro le quinte che assomiglia a:

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

In effetti, queste sono solo alcune delle tue possibili opzioni, in cui ci sono molti modi diversi per raggiungere lo stesso obiettivo e in cui hai anche la libertà di fare il tuo.

Le libertà di digitazione libera e senza schema di NoSQL dovrebbero essere abbracciate e non dovresti preoccuparti di provare a seguire una struttura rigida e predefinita con cui potresti avere familiarità quando usi un RDBMS.

In conclusione, non esiste un vero modo giusto per memorizzare i dati in Redis, ad es. Il client C# Redis fa alcune ipotesi al fine di fornire un'API di alto livello attorno ai POCO e blob i POCO nei valori di stringa binari sicuri di Redis, sebbene altri client preferiscano invece archiviare le proprietà di un'entità in Redis Hash (Dizionari) . Entrambi funzioneranno.