Ответ 1
Вместо повторного хэша есть много другой документации, которая существует в дикой природе, я перечислил пару для некоторой дополнительной информации о Redis + ServiceStack Redis Client:
- О чем подумать при разработке приложения NoSQL Redis
- Проектирование базы данных NoSQL с использованием Redis
- Общий обзор Redis и .NET
- Сквозное управление версиями и миграция данных с помощью клиента С# Redis
Нет волшебства - Redis - пустой холст
Сначала я хочу указать, что использование Redis в качестве хранилища данных просто предоставляет пустой холст и не имеет понятия самозанятых объектов. то есть он просто обеспечивает доступ к распределенным структурам данных comp-sci. Как отношения хранятся, в конечном счете, до клиентского драйвера (например, ServiceStack С# Redis Client) или разработчика приложения, используя операции примитивной обработки данных Redis. Поскольку все основные структуры данных реализованы в Redis, вы в основном имеете полную свободу в отношении того, как вы хотите структурировать и хранить ваши данные.
Подумайте, как бы вы структурировали отношения в коде
Итак, лучший способ подумать о том, как хранить вещи в Redis, - это полностью игнорировать то, как данные хранятся в таблице RDBMS, и думать о том, как они хранятся в вашем коде, т.е. использовать встроенные классы коллекции С# в памяти - что Redis отражает поведение со своими серверными структурами данных.
Несмотря на отсутствие понятия связанных объектов, встроенные структуры данных Установить и SortedSet обеспечивают идеальный способ хранения индексов. Например. В коллекции Redis Set хранится максимум 1 вхождение элемента. Это означает, что вы можете безопасно добавлять элементы/ключи/идентификаторы к нему и не заботятся о том, существует ли элемент уже в качестве конечного результата, если бы вы его назвали 1 или 100 раз, то есть он идемпотент, и, в конечном счете, только один элемент остается в памяти набор. Таким образом, общий случай использования заключается в том, что хранение графа объектов (агрегированного корня) заключается в том, чтобы хранить идентификаторы дочерних объектов (иначе называемые внешние ключи) в наборе каждый раз, когда вы сохраняете модель.
Визуализация ваших данных
Для хорошей визуализации того, как объекты хранятся в Redis, я рекомендую установить Redis Admin UI, который хорошо работает с ServiceStack С# Redis Client как он использует соглашение о присвоении имен ключа ниже, чтобы обеспечить хорошее иерархическое представление, группируя свои типизированные сущности вместе (несмотря на все ключи, существующие в одном и том же глобальном пространстве ключей).
Чтобы просмотреть и отредактировать Entity, нажмите ссылку Изменить, чтобы просмотреть и изменить выбранное внутреннее представление JSON. Надеемся, вы сможете принять правильные решения о том, как создавать свои модели, как только вы сможете увидеть, как они хранятся.
Как хранится POCO/Entities
Клиент С# Redis работает с любыми POCOs, у которых есть единственный первичный ключ, который по умолчанию должен быть Id
(хотя это соглашение переопределяется с ModelConfig),
По существу, POCOs хранится в Redis как сериализованный JSON с использованием typeof(Poco).Name
и Id
, используемых для формирования уникального ключа для этого экземпляра. Например:
urn:Poco:{Id} => '{"Id":1,"Foo":"Bar"}'
POCOs в С# Client обычно сериализуются с использованием ServiceStack fast Json Serializer, где сериализуются только свойства с публичными геттерами (и публичные сеттеры для получения де-сериализованная спина).
Значение по умолчанию переопределяется с помощью [DataMember]
attrs, но не рекомендуется, поскольку оно угадывает ваши POCOs.
Объекты blobbed
Итак, зная, что POCOs в Redis просто blobbed, вы хотите сохранить неагрегатные корневые данные в своих POCO как общедоступные свойства (если вы не намерены хранить избыточные данные). Хорошим соглашением является использование методов для получения связанных данных (поскольку он не будет сериализован), но также сообщает вашему приложению, какие методы делают удаленные вызовы для чтения данных.
Итак, вопрос о том, следует ли хранить Feed с помощью Пользователь, является ли он неагрегировать данные root, то есть, хотите ли вы получить доступ к пользователи питаются вне контекста пользователя? Если нет, то оставьте свойство List<Feed> Feeds
в типе User
.
Поддержание пользовательских индексов
Если вы хотите, чтобы все каналы были доступны независимо, т.е. с помощью redisFeeds.GetById(1)
, тогда вы захотите сохранить его за пределами пользователя и сохранить индекс, связывающий 2 объекта.
Как вы заметили, существует множество способов хранения отношений между сущностями и того, как вы это делаете, во многом зависит от предпочтений. Для дочернего объекта в родительском > дочернем отношениях вы всегда хотите сохранить ParentId с дочерним объектом. Для родителя вы можете либо выбрать коллекцию ChildIds с моделью, а затем сделать одну выборку для всех дочерних объектов, чтобы повторно увлажнить модель.
Другой способ - поддерживать индекс за пределами родительского dto в своем собственном Установить для каждого родительского экземпляра. Некоторые хорошие примеры этого в С# Исходный код Redis Демо-версия StackOverflow, где отношения Users > Questions
и Users > Answers
хранятся в:
idx:user>q:{UserId} => [{QuestionId1},{QuestionId2},etc]
idx:user>a:{UserId} => [{AnswerId1},{AnswerId2},etc]
Хотя С# RedisClient включает поддержку условного соглашения родителя/ребенка по умолчанию через TParent.StoreRelatedEntities(), TParent.GetRelatedEntities<TChild>()
и TParent.DeleteRelatedEntities()
API, где индекс сохраняется за сценой, которая выглядит следующим образом:
ref:Question/Answer:{QuestionId} => [{answerIds},..]
Эффективно это лишь некоторые из ваших возможных вариантов, где есть много разных способов достижения той же цели и в которой у вас также есть свобода от казни.
Отсутствие схем NoSQL, свободная печать, должны быть приняты, и вам не следует беспокоиться о том, чтобы попытаться следовать жесткой, заранее определенной структуре, с которой вы можете ознакомиться при использовании РСУБД.
В заключение нет реального правильного пути для хранения данных в Redis, например. Клиент С# Redis делает некоторые предположения для предоставления API высокого уровня вокруг POCOs и он блокирует POCOs в двоично-безопасных строковых значениях Redis - хотя есть и другие клиенты, предпочитающие хранить свойства объектов в Redis Hashes (словари) вместо, Оба будут работать.