Ответ 1
Я не могу ответить на вопрос о том, когда использовать хранилище данных с ключом (здесь kv), но я могу показать вам некоторые примеры и ответить на ваш пример stackoverflow.
С доступом к базе данных, большая часть того, что вам нужно, это kv-магазин. Например, пользователь входит в систему с именем пользователя "joe". Таким образом, вы просматриваете "user: joe" в своей базе данных и получаете его пароль (хэш конечно). Или, может быть, у вас есть пароль под "user: pass: joe", это действительно неважно. Если это было переполнение стека, и вы отображали страницу http://stackoverflow.com/questions/6935566/when-to-use-a-key-value-store-for-web-development
, вы бы искали "вопрос: 6935566" и использовали это. Легко видеть, как магазины kv могут решить большинство ваших проблем.
Я хотел бы сказать, что kv-хранилище является подмножеством функциональности, предоставляемой традиционной RDMS. Это связано с тем, что дизайн традиционной RDMS обеспечивает множество проблем масштабирования и, как правило, теряет функции по мере масштабирования. В магазинах kv нет таких функций, поэтому они не ограничивают вас. Однако эти функции часто могут создаваться в любом случае, сконструированные из ядра для масштабируемости (потому что это становится сразу же очевидным, если они не являются).
Однако это не означает, что есть вещи, которые вы не можете сделать. Например, вы указываете запрос. Это ловушка многих магазинов kv, поскольку они, как правило, агностик ценности (не всегда истинный, например, redis и т.д.) И не имеют возможности найти то, что вы ищете. Хуже того, они не предназначены для этого быстро, они просто очень быстро ищут ключ.
Одним из решений этой проблемы является сортировка ваших ключей лексикографически и разрешение запросов диапазона. Это по существу "дайте мне все между вопросом: 1 и вопрос: 5". Теперь этот пример довольно бесполезен, но есть много применений запросов диапазона.
Вы сказали, что хотите, чтобы все дома составляли более 100 000 долларов. Если вы хотите, чтобы это было сделано, вы бы создали индекс домов по цене. Скажем, у вас были следующие дома.
house:0 -> {"color":"blue","sold":false,"city":"Stackoverville","price":500000}
house:1 -> {"color":"red","sold":true,"city":"Toronto","price":150000}
house:2 -> {"color":"beige","sold":false,"city":"Toronto","price":40000}
house:3 -> {"color":"blue","sold":false,"city":"The Blogosphere","price":110000}
В SQL вы будете хранить каждое поле в столбце, а затем все это в одном (в данном случае JSON) документе. И мог SELECT * FROM houses WHERE price > 100000
. Кажется, все прекрасно и денди, но если индекс не построен, это требует взглянуть на каждый дом в вашем столе и проверить его цену, которая, если у вас есть несколько миллионов домов, может быть медленной. Итак, с магазином kv вам нужен индекс. Основное различие заключается в том, что база данных SQL молча выполняла бы медленную вещь, где хранилище kv не было бы.
Если у вас нет запросов на диапазон, вам нужно будет привязать свой индекс в одном документе, что значительно облегчит его обновление, а значит, вам нужно будет загрузить весь индекс для каждого запроса, опять же, ограничивая масштабируемость.
house:index:price -> [{"price":500000,"id":"0"},{"price":150000,"id":"1"},{"price":110000,"id":"3"},{"price":40000,"id":"2"}]
Но если у вас есть запросы диапазона (часто называемые ключевыми словами), вы можете создать такой индекс:
house:index:price:040000 -> 2
house:index:price:110000 -> 3
house:index:price:150000 -> 1
house:index:price:500000 -> 0
И затем вы можете запросить ключи между house:index:price:100000
и house:index:price::
(символ ":" - символ после "9" ), и вы получите [3,1,0]
, который является всеми домами, более дорогими, чем 100 000 долларов США ( они также помогают в порядке). Еще одна приятная вещь в этом заключается в том, что они, вероятно, будут на одном "разделе" вашего кластера, поэтому этот запрос займет примерно столько же времени, что и "singe get" (плюс крошечные дополнительные накладные расходы), или два получат, если ваш диапазон будет переходить граница сервера (но это можно сделать параллельно!).
Итак, это показывает, как делать запросы в хранилище kv. Вы можете запросить все, что можно заказать в виде строки (что угодно), и быстро просмотреть ее. Если у вас нет запросов на диапазон, вам нужно будет хранить весь ваш индекс под одним ключом, который отстой, но если у вас есть запросы к диапазону, это очень хорошо и очень быстро. Вот более сложный пример.
Я хочу, чтобы непроданные дома в Торонто составляли менее 100 000 долларов. Мне просто нужно разработать свой индекс. (Я добавил в несколько домов, чтобы сделать его более значимым). Сначала подумал, что вы можете просто создать еще один индекс для каждого свойства, но вы быстро поймете, что это означает, что вам нужно выбрать каждый непроданный дом и загрузить его из базы данных. (Это то, что я имел в виду, когда я сказал, что проблемы масштабирования сразу же очевидны.) Решение заключается в использовании мультииндекса. После создания вы можете выбрать именно нужные значения.
house:index:sold:city:price:f~Fooville~000010:5 -> ""
house:index:sold:city:price:f~Toronto~040000:2 -> ""
house:index:sold:city:price:f~Toronto~140000:4 -> ""
house:index:sold:city:price:t~Stackoverville~500000:0 -> ""
house:index:sold:city:price:t~The Blogosphere~110000:3 -> ""
house:index:sold:city:price:t~Toronto~150000:1 -> ""
Теперь, в отличие от последнего примера, я помещаю идентификатор в ключ. Это позволяет двум домам иметь одинаковые свойства. Я мог бы объединить их в значение, но добавление удаляющих индексов становится более сложным. Я также решил отделить мои данные с помощью ~
. Это потому, что оно лексикографически после всех букв, гарантируя, что полное имя будет отсортировано, и мне не нужно вставлять каждый город в ту же длину. В производственной системе я бы, вероятно, использовал байты 255 или 0.
Теперь диапазон house:index:sold:city:price:f~Toronto~100000
- house:index:sold:city:price:f~Toronto~~
выберет все дома, соответствующие запросу. И важно отметить, что запрос масштабируется линейно с количеством результатов. Это означает, что вам нужно создать индекс для каждого набора свойств, который вы хотите индексировать (хотя индекс в нашем примере также работает для проданных и проданных запросов). Это может показаться большой работой, но, в конце концов, вы понимаете, что именно это вы делаете, а не в своей базе данных. Я уверен, что мы скоро увидим библиотеки для такого рода вещей: D
После растягивания темы немного, я показал:
- Некоторые использования хранилища kv.
- Как выполнять запросы в хранилище kv.
Я думаю, что вы обнаружите, что kv-магазины достаточно для многих приложений и часто обеспечивают лучшую производительность и доступность, чем традиционные RDMS. При этом каждое приложение отличается и поэтому невозможно ответить на исходный вопрос.