Усі відповіді (на момент написання цієї статті) припускають, що кожен з 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
. Тепер у вашій базі даних і в Redis вас 105, і ви можете отримати їх, 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, або зберігання документів.