Все ответы (на момент написания этой статьи) предполагают, что каждый из Redis, MongoDB и, возможно, реляционной базы данных на основе SQL, по сути, является одним и тем же инструментом: «хранить данные». Они вообще не рассматривают модели данных.
MongoDB: сложные данные
MongoDB - это хранилище документов. Для сравнения с реляционной базой данных на основе SQL: реляционные базы данных упрощаются до индексированных CSV-файлов, каждый из которых представляет собой таблицу; хранилища документов упрощаются до индексированных файлов JSON, каждый из которых является документом, с несколькими файлами, сгруппированными вместе.
Файлы JSON похожи по структуре на файлы XML и YAML, а также на словари, как в Python, поэтому подумайте о своих данных в такой иерархии. При индексации структура является ключом: документ содержит именованные ключи, которые содержат дополнительные документы, массивы или скалярные значения. Рассмотрим приведенный ниже документ.
{
_id: 0x194f38dc491a,
Name: "John Smith",
PhoneNumber:
Home: "555 999-1234",
Work: "555 999-9876",
Mobile: "555 634-5789"
Accounts:
- "379-1111"
- "379-2574"
- "414-6731"
}
Приведенный выше документ имеет ключ PhoneNumber.Mobile
, который имеет значение 555 634-5789
. Вы можете искать в коллекции документов, где ключ PhoneNumber.Mobile
имеет значение; они проиндексированы.
Он также имеет массив, Accounts
который содержит несколько индексов. Можно запросить документ, который Accounts
содержит ровно некоторое подмножество значений, все некоторое подмножество значений или какое -либо подмножество значений. Это означает, что вы можете искать Accounts = ["379-1111", "379-2574"]
и не найти выше; Вы можете найти Accounts includes ["379-1111"]
и найти вышеуказанный документ; и вы можете найти Accounts includes any of ["974-3785","414-6731"]
и найти вышеупомянутое, и любой другой документ включает в себя учетную запись "974-3785", если таковая имеется.
Документы идут так глубоко, как вы хотите. PhoneNumber.Mobile
может содержать массив или даже поддокумент ( PhoneNumber.Mobile.Work
и PhoneNumber.Mobile.Personal
). Если ваши данные хорошо структурированы, документы являются большим шагом по сравнению с реляционными базами данных.
Если ваши данные в основном плоские, реляционные и жестко структурированные, вам лучше использовать реляционную базу данных. Опять же, большой признак в том, что ваши модели данных лучше всего подходят для коллекции взаимосвязанных файлов CSV или коллекции файлов XML / JSON / YAML.
Для большинства проектов вам придется идти на компромисс, принимая небольшой обходной путь в некоторых небольших областях, где хранилища SQL или документов не подходят; для некоторых крупных и сложных проектов, в которых хранится широкий разброс данных (много столбцов; строки не имеют значения), имеет смысл хранить некоторые данные в одной модели и другие данные в другой модели. Facebook использует и базу данных SQL, и графическую базу данных (где данные помещаются в узлы, а узлы соединяются с другими узлами); Craigslist использовал MySQL и MongoDB, но пытался полностью перейти на MongoDB. Это те места, где диапазон и взаимосвязь данных сталкиваются с существенными препятствиями, если рассматривать их в рамках одной модели.
Redis: ключ-значение
Redis - это, в основном, хранилище ключей. Redis позволяет вам дать ему ключ и найти единственное значение. Redis сам может хранить строки, списки, хэши и некоторые другие вещи; тем не менее, он выглядит только по имени.
Аннулирование кэша является одной из трудных проблем информатики; другой называет вещи. Это означает, что вы будете использовать Redis, когда хотите избежать сотен лишних поисков в фоновом режиме, но вам придется выяснить, когда вам нужен новый поиск.
Наиболее очевидным случаем аннулирования является обновление при записи: если вы читаете user:Simon:lingots = NOTFOUND
, вы можете SELECT Lingots FROM Store s INNER JOIN UserProfile u ON s.UserID = u.UserID WHERE u.Username = Simon
и сохранить результат 100
, как SET user:Simon:lingots = 100
. Затем , когда вы наградите Simon 5 lingots, вы читаете user:Simon:lingots = 100
, SET user:Simon:lingots = 105
и UPDATE Store s INNER JOIN UserProfile u ON s.UserID = u.UserID SET s.Lingots = 105 WHERE u.Username = Simon
. Теперь у вас есть 105 в вашей базе данных и в Redis, и вы можете получить user:Simon:lingots
без запросов к базе данных.
Второй случай - обновление зависимой информации. Допустим, вы генерируете фрагменты страницы и кэшируете их вывод. Заголовок показывает опыт игрока, уровень и сумму денег; Страница профиля игрока имеет блок, который показывает их статистику; и так далее. Игрок получает некоторый опыт. Ну, теперь у вас есть несколько templates:Header:Simon
, templates:StatsBox:Simon
, templates:GrowthGraph:Simon
и так далее поля , где вы кэшировать вывод полдюжины базы данных запросов , выполняемых через механизм шаблонов. Обычно, когда вы отображаете эти страницы, вы говорите:
$t = GetStringFromRedis("templates:StatsBox:" + $playerName);
if ($t == null) {
$t = BuildTemplate("StatsBox.tmpl",
GetStatsFromDatabase($playerName));
SetStringInRedis("Templates:StatsBox:" + $playerName, $t);
}
print $t;
Поскольку вы только что обновили результаты GetStatsFromDatabase("Simon")
, вы должны templates:*:Simon
исключить из кэша ключ-значение. Когда вы пытаетесь отобразить любой из этих шаблонов, ваше приложение будет собирать данные из вашей базы данных (PostgreSQL, MongoDB) и вставлять их в ваш шаблон; затем он сохранит результат в Redis и, надеюсь, не будет беспокоиться о том, чтобы выполнять запросы к базе данных и отображать шаблоны при следующем отображении этого блока вывода.
Redis также позволяет вам создавать очереди сообщений подписчика издателя и тому подобное. Это совсем другая тема. Дело в том, что Redis - это кэш ключ-значение, который отличается от реляционной базы данных или хранилища документов.
Вывод
Выберите ваши инструменты в зависимости от ваших потребностей. Самой большой потребностью обычно является модель данных, поскольку она определяет, насколько сложным и подверженным ошибкам является ваш код. Специализированные приложения будут опираться на производительность, места, где вы пишете все в смеси C и Assembly; большинство приложений просто обрабатывают обобщенный случай и используют систему кэширования, такую как Redis или Memcached, которая намного быстрее, чем высокопроизводительная база данных SQL или хранилище документов.