Кэш-память без схемы: NoSQL или другие альтернативы?
Я оцениваю ряд реализаций NoSQL (RavenDB и MongoDB на данный момент) как средство решения определенного набора требований, которые включают хранение / поиск данных, которые не требуют схем. Я хочу получить некоторую обратную связь о том, является ли NoSQL направлением, в котором я должен искать, или есть ли другие (потенциально более простые) варианты.
По сути, у нас есть программный продукт, который (помимо прочего) определяет базовую модель предметной области, которая состоит из нескольких связанных сущностей, каждый из которых имеет ряд атрибутов (ключ / значение). Когда мы предоставляем заказчику, мы работаем с ним, чтобы настроить атрибуты и значения, которые, по сути, являются конфигурацией системы. Это довольно просто, и поскольку дизайн известен заранее, нам не нужно ничего динамичного, чтобы добиться этого и заставить его работать (мы будем использовать RDBMS). Атрибуты не известны заранее, но, опять же, это не проблема, так как эта часть системы вращается вокруг модели атрибутов.
Проблема в том, что для разных клиентов, и ПОСЛЕ того, как мы выпускаем и работаем, мы обнаруживаем, что нам нужно запросить определенные наборы данных атрибутов, о которых мы ничего не знали, когда мы компилировали и выпускали код (и до того, как мы настроили атрибуты для клиент). В основном нам нужно получить данные из карт атрибутов, которые мы можем сохранить (мы не будем знать структуру заранее), а затем запросить эти данные позже, что мы не можем предвидеть. Сейчас мы думаем о том, что мы можем создать хуки, которые будут попадать во время обработки, и позволить нам подключать библиотеки (вероятно, через MEF), которые создают данные для их хранения, а затем запрашивать их позже, когда это необходимо (не для отчетов - обычно для создания дополнительных данных / атрибутов).
(Обратите внимание, что создание библиотек перехвата и подключаемых модулей является отдельной проблемой и не является частью этого вопроса.)
Распространенным сценарием может быть: "Я хочу знать, сколько раз ххх происходило за последние 10 дней". Поэтому я бы создал плагин, который распознал бы, что произошел ххх, и записал бы его в хранилище данных с датой / временем. Затем я создал бы другой плагин (вероятно, в той же DLL), который выполнял бы запрос, и добавил бы в модель атрибут с именем "CountOfxxxInLast10Days". Другой сценарий может заключаться в создании настраиваемых поисков. Поэтому у меня может быть плагин, который запускается при запуске для создания / обновления таблицы данных поиска, которая может преобразовать одно значение атрибута в другое, или (более вероятно) диапазон значений, который будет преобразован в значения поиска. Таким образом, плагин преобразования может добавить таблицу со столбцами: bottom_value, top_value, множитель, а плагин запроса будет запрашивать таблицу, используя значение атрибута, например, "Множитель SELECT ИЗ таблицы WHERE [attribute_value] BETWEEN bottom_value AND top_value". Результат может добавить результат к атрибуту с именем "Multiplier".
В некоторых случаях старые данные могут быть удалены после определенного периода времени. В первом сценарии, описанном выше, может быть желательно удалить данные из хранилища / кэша, которые были старше десяти дней.
В других случаях данные должны будут постоянно сохраняться, как во втором сценарии выше. Возможно, эти данные могут быть просто воссозданы при запуске, а не храниться в постоянном хранилище.
Дополнительные требования:
- Хранилище данных / кеш можно создавать резервные копии и восстанавливать в режиме онлайн
- Может быть заменен / восстановлен из последней резервной копии в случае сбоя
- Данные переживают такие события, как перезагрузка компьютера
- Проверенная / испытанная технология
На данный момент мы довольно привержены платформе.Net, поэтому любой вариант должен иметь надежный клиент /API.Net.
1 ответ
Есть три возможных варианта, каждый со своими плюсами и минусами.
Повторное использование СУБД
Вы уже храните сущности в реляционной базе данных. Вы можете хранить неопределенные атрибуты в дополнительной таблице, которая имеет Key
а также Value
колонка и EntityId
столбец, который ссылается на объект, которому принадлежат атрибуты. По сути, вы будете использовать часть своей базы данных в качестве хранилища значений ключей.
Преимущества:
- Все ваши данные хранятся в одной базе данных, что означает:
- вы можете получить сущность и все ее атрибуты в одном запросе,
- Ваше приложение менее сложное, поскольку оно должно взаимодействовать только с одной базой данных.
- Вы получаете все преимущества ACID реляционной базы данных.
Недостатки:
- Реляционные базы данных не предназначены для хранения значений ключей, поэтому у вас могут возникнуть проблемы с производительностью. Однако я ожидаю, что снижение производительности будет минимальным, если только вы не планируете хранить очень-очень большое количество атрибутов.
Используйте хранилище ключей
Хранилища ключей-значений, такие как Redis и Riak или более продвинутый Apache Cassandra, оптимизированы для хранения пар ключ-значение (нет ничего удивительного в этом...). Вы можете использовать хранилище значений ключей рядом с вашей СУБД, предназначенное для хранения атрибутов при сохранении сущностей в вашей СУБД.
Преимущества:
- Лучшая производительность, чем у СУБД, особенно с большими объемами данных.
- Проще масштабировать, так как они не ограничены свойствами ACID.
Недостатки:
- Нет гарантированных свойств ACID, но так называемая возможная согласованность, означающая, что сохраненные данные не всегда могут быть согласованными на разных серверах. Однако вам придется иметь дело только с этим, если вы уменьшаете масштаб. Кроме того, большинство хранилищ ключей и значений позволяют настроить его строгость в отношении согласованности, чтобы помочь преодолеть эту проблему.
- Ваше приложение будет работать в двух отдельных базах данных, что увеличивает сложность вашего приложения.
Используйте базу данных документов
Вы можете использовать базу данных документов для хранения только атрибутов. Но вы также можете сделать решающий шаг и сохранить все в базе данных документов, включая ваши сущности.
Преимущества:
- Все ваши данные хранятся в одной базе данных, что означает:
- вы можете извлечь сущность и все ее атрибуты в одной операции, так же как вы сохранили бы всю сущность, включая ее атрибуты, в одном документе.
- Ваше приложение менее сложное, поскольку оно должно взаимодействовать только с одной базой данных.
- Проще масштабировать, так как они не ограничены свойствами ACID.
- Базы данных документов не ограничиваются только значениями ключей, поэтому, если вам когда-либо понадобится сохранить более сложный атрибут, вы уже готовы.
Недостатки:
- Нет гарантий ACID, как в хранилищах ключей. Большинство баз данных документов могут быть настроены для преодоления проблем согласованности.
- Нет понимания отношений между сущностями, как в СУБД. Реляционная модель нормализуется, тогда как документы денормализуются, чтобы преодолеть наличие множества отношений. Это может быть или не быть большим недостатком, в зависимости от вашей конкретной модели предметной области.
Технологии базы зрелых документов
Apache CouchDB имеет большой список приложений, использующих его, и получает положительные отзывы от сообщества Stack Overflow. У него есть несколько драйверов для.NET, но я не могу сказать вам, насколько зрелы эти драйверы.
MongoDB имеет довольно внушительный список производственных рабочих мест. Существует три основных драйвера для.NET, которые кажутся хорошего качества.
RavenDB имеет отличную поддержку.NET, так как он был разработан для платформы.NET. Однако мне не удалось найти примеры больших производственных сред, работающих на RavenDB. Тем не менее, я думаю, что это определенно стоит изучить.
У меня нет практического опыта работы с любым из них в производственных средах, поэтому я не знаю точно, насколько легко их выполнять резервное копирование / восстановление. Но с учетом того факта, что эти системы NoSQL не такие жесткие, как системы RDBMS, я думаю, что их проще резервировать / восстанавливать без простоев, чем RDBMS.