sql >> Base de Datos >  >> NoSQL >> Redis

ServiceStack.Net Redis:almacenamiento de objetos relacionados frente a identificadores de objetos relacionados

En lugar de volver a recopilar una gran cantidad de otra documentación que está disponible, enumeraré un par para obtener información general sobre Redis + ServiceStack's Redis Client:

  • Qué pensar al diseñar una aplicación NoSQL Redis
  • Diseño de una base de datos NoSQL con Redis
  • Descripción general de Redis y .NET
  • Control de versiones sin esquema y migraciones de datos con C# Redis Client

No hay magia:Redis es un lienzo en blanco

En primer lugar, quiero señalar que el uso de Redis como almacén de datos solo proporciona un lienzo en blanco y no tiene ningún concepto de entidades relacionadas por sí mismo. es decir, solo proporciona acceso a estructuras de datos comp-sci distribuidas. La forma en que se almacenan las relaciones depende en última instancia del controlador del cliente (es decir, ServiceStack C# Redis Client) o del desarrollador de la aplicación, mediante el uso de operaciones de estructura de datos primitivas de Redis. Dado que todas las estructuras de datos principales se implementan en Redis, básicamente tiene total libertad sobre cómo desea estructurar y almacenar sus datos.

Piense cómo estructuraría las relaciones en el código

Entonces, la mejor manera de pensar en cómo almacenar cosas en Redis es ignorar por completo cómo se almacenan los datos en una tabla RDBMS y pensar en cómo se almacenan en su código, es decir, usando las clases de colección de C# integradas en la memoria:que Redis refleja en el comportamiento con sus estructuras de datos del lado del servidor.

A pesar de no tener un concepto de entidades relacionadas, el Conjunto integrado de Redis y Conjunto Ordenado Las estructuras de datos proporcionan la forma ideal de almacenar índices. P.ej. Conjunto de Redis la colección solo almacena un máximo de 1 ocurrencia de un elemento. Esto significa que puede agregarle elementos/claves/identificadores de manera segura y no preocuparse si el elemento ya existe, ya que el resultado final será el mismo si lo llamó 1 o 100 veces, es decir, es idempotente y, en última instancia, solo 1 elemento permanece almacenado en el conjunto. Entonces, un caso de uso común es cuando se almacena un gráfico de objetos (raíz agregada) para almacenar los Id. de entidades secundarias (también conocidas como claves externas) en un conjunto cada vez que guarda el modelo.

Visualización de sus datos

Para una buena visualización de cómo se almacenan las entidades en Redis, recomiendo instalar la interfaz de usuario de administración de Redis, que funciona bien con el cliente C# Redis de ServiceStack, ya que utiliza la siguiente convención de nomenclatura clave para proporcionar una buena vista jerárquica, agrupando las entidades escritas juntas (a pesar de todas las claves). existentes en el mismo espacio de claves global).

Para ver y editar una Entidad, haga clic en Editar enlace para ver y modificar la representación JSON interna de la entidad seleccionada. Con suerte, podrá tomar mejores decisiones sobre cómo diseñar sus modelos una vez que pueda ver cómo están almacenados.

Cómo se almacenan POCO / Entidades

El cliente C# Redis funciona con cualquier POCO que tenga una única clave principal, que de forma predeterminada se espera que sea Id (aunque esta convención se puede anular con ModelConfig). Esencialmente, los POCO se almacenan en Redis como JSON serializado con typeof(Poco).Name y el Id se utiliza para formar una clave única para esa instancia. Por ejemplo:

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

Los POCO en el cliente de C# se serializan convencionalmente mediante el rápido serializador Json de ServiceStack, donde solo se serializan las propiedades con captadores públicos (y los establecedores públicos para volver a deserializarse).

Los valores predeterminados se pueden anular con [DataMember] attrs pero no recomendado ya que afea tus POCO.

Las entidades están blobbed

Entonces, sabiendo que los POCO en Redis solo están blobbed, solo desea mantener los datos raíz no agregados en sus POCO como propiedades públicas (a menos que deliberadamente desee almacenar datos redundantes). Una buena convención es usar métodos para obtener los datos relacionados (ya que no se serializarán), pero también le dice a su aplicación qué métodos realizan llamadas remotas para leer datos.

Entonces, la pregunta sobre si el Feed debe almacenarse con el Usuario es si se trata o no de datos raíz no agregados, es decir, si desea o no acceder a las fuentes de los usuarios fuera del contexto del usuario. Si no, entonces deje la List<Feed> Feeds propiedad en el User tipo.

Mantenimiento de índices personalizados

Sin embargo, si desea mantener todos los feeds accesibles de forma independiente, es decir, con redisFeeds.GetById(1) entonces querrá almacenarlo fuera del usuario y mantener un índice que vincule las 2 entidades.

Como ha notado, hay muchas formas de almacenar relaciones entre entidades y cómo hacerlo es en gran medida una cuestión de preferencia. Para la entidad secundaria en un padre>secundario relación siempre querrías almacenar el ParentId con la entidad secundaria. Para el padre, puede optar por almacenar una colección de ChildIds con el modelo y luego realice una búsqueda única para todas las entidades secundarias para rehidratar el modelo.

Otra forma es mantener el índice fuera del dto principal en su propio Conjunto para cada instancia principal. Algunos buenos ejemplos de esto se encuentran en el código fuente de C# de la demostración de Redis StackOverflow donde la relación de Users > Questions y Users > Answers se almacena en:

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

Aunque C# RedisClient incluye soporte para una convención padre/hijo predeterminada a través de TParent.StoreRelatedEntities(), TParent.GetRelatedEntities<TChild>() y TParent.DeleteRelatedEntities() API donde se mantiene un índice detrás de escena que se parece a:

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

Efectivamente estas son solo algunas de tus posibles opciones, donde hay muchas maneras diferentes de conseguir un mismo fin y en las que también tienes la libertad de rodar la tuya propia.

Las libertades de tipeo suelto y sin esquemas de NoSQL deben adoptarse y no debe preocuparse por tratar de seguir una estructura rígida y predefinida con la que puede estar familiarizado al usar un RDBMS.

En conclusión, no hay una forma correcta real para almacenar datos en Redis, p. El cliente C# Redis hace algunas suposiciones para proporcionar una API de alto nivel alrededor de los POCO y bloquea los POCO en los valores de cadena binarios seguros de Redis, aunque hay otros clientes que preferirán almacenar las propiedades de las entidades en Redis Hashes (diccionarios) en su lugar. . Ambos funcionarán.