何时使用键值存储进行Web开发?

Jac*_*joi 14 memcached web-hosting web-applications redis

我有点像菜鸟,所以我去...

什么时候有人使用键值(Redis,memcache等)商店进行Web开发?实际的用例最有帮助.

我的困惑是,一个简单的数据库似乎功能更多,因为据我所知,它可以做一切键值存储可以做的事情PLUS它还允许你进行过滤/查询.意思是,根据我的理解,你不能像__CODE__使用键值存储那样进行过滤 .

更新:

让我们让这个例子更真实.让我们假装StackOverflow使用键值存储(memcache,redis等).

键值存储如何帮助Stackoverflow托管需求?

Kev*_*Cox 13

我无法回答何时使用键值(此处为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".现在这个例子相当无用,但范围查询有很多用途.

你说你希望所有的房子都超过10万美元.如果你想能够做到这一点,你会按价格创建房屋指数.说你有以下房子.

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}
Run Code Online (Sandbox Code Playgroud)

在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"}]
Run Code Online (Sandbox Code Playgroud)

但是如果你有范围查询(通常称为键盘),你可以创建一个这样的索引:

house:index:price:040000 -> 2
house:index:price:110000 -> 3
house:index:price:150000 -> 1
house:index:price:500000 -> 0
Run Code Online (Sandbox Code Playgroud)

然后你可以要求之间的键house:index:price:100000house:index:price::(在":"字是"9"之后的字符),你会得到[3,1,0]这所有的房子超过$ 100 000更昂贵的(它们也是有益的顺序).关于这一点的另一个好处是它们可能会在你的集群的一个"分区"上,所以这个查询将花费大约相同的时间来获得(加上额外的小额转移开销)或者如果你的范围恰好超过两个则获得服务器边界(但这些可以并行完成!).

这样就说明了如何在kv商店中进行查询.您可以查询任何可以作为字符串排序的内容(几乎任何内容)并快速查找.如果您没有范围查询,则需要将整个索引存储在一个很糟糕的键下,但是如果您有范围查询,则非常好,而且非常快.这是一个更复杂的例子.

我希望多伦多未售出的房屋价值低于10万美元.我只需要设计我的指数.(我添加了几个房子以使其更有意义)首先想到你可能只为每个属性构建另一个索引,但你很快就会意识到这意味着你必须选择每个未售出的房子并从数据库下载它.(当我说缩放问题很明显时,这就是我的意思.)解决方案是使用多索引.构建完成后,您可以精确选择所需的值.

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         -> ""
Run Code Online (Sandbox Code Playgroud)

现在,与上一个例子不同,我把id放在密钥中.这允许两个房子具有相同的属性.我可以将它们合并到值中,但是添加删除索引变得更加困难.我还选择将数据与a分开~.这是因为它在所有字母之后按字典顺序排列,确保全名将被分类,而且我不必将每个城市填充到相同的长度.在生产系统中,我可能会使用255或0字节.

现在范围house:index:sold:city:price:f~Toronto~100000- house:index:sold:city:price:f~Toronto~~将选择与查询匹配的所有房屋.需要注意的重要一点是查询与结果数量呈线性关系.这意味着您必须为要编制索引的每组属性构建索引(尽管我们示例中的索引也适用于已售出和已售出城市的查询).这可能看起来像很多工作,但最后你意识到只是你在做,而不是你的数据库.我相信我们很快就会开始看到图书馆出现这种事情:D

在略微扩展了主题之后,我已经展示了:

  • kv商店的一些用途.
  • 如何在kv商店中进行查询.

我认为您会发现kv-store对于许多应用程序来说足够了,并且通常可以提供比传统RDMS更好的性能和可用性.话虽如此,每个应用程序都是不同的,因此,回答原始问题是不可能的.

  • 这是我在 StackOverflow 上读过的内容最丰富、最令人大开眼界的答案之一。在阅读本文之前,我不知道数据库的内部结构实际上是如何工作的。现在我准备好用 kv 存储来构建一些东西了,我之前会说“好吧,你只能用 SQL 来做到这一点”。 (2认同)

小智 5

不要将NoSQL类型数据库与memcached(不打算永久存储数据)混淆.

memcached的典型用途是存储一些可由Web服务器集群访问的查询结果 - 即.共享缓存.例如.在此页面上是相关帖子的列表,数据库可能需要做一些工作才能生成该列表.如果您每次有人加载页面时都这样做,那么您将为数据库创建大量工作.相反,第一次检索的结果可以存储在memcached服务器上,其中密钥是页面ID.然后,群集中的任何Web服务器都可以非常快速地获取该信息,而无需经常访问数据库.一段时间后,缓存条目将被memcached清除,以便旧文章的结果不会占用空间.[免责声明:我不知道StackOverflow是否真的这样做].

另一方面,"NoSQL"数据库用于永久存储信息.如果您的数据模式非常简单,那么查询也是如此,那么它可能比标准SQL数据库更快.许多Web应用程序不需要非常复杂的数据库,因此NoSQL数据库非常适合.


alp*_*ero 5

noSQL 有两个通用的可行用例:

  1. 快速应用开发
  2. 可大规模扩展的系统

大多数 noSQL 解决方案实际上是无模式的;需要更少的仪式来操作;重量轻(就 API 而言);与更规范的关系持久性系统相比,提供显着的性能提升,表明它们适用于上述 2 个用例(一般意义上)。

愤世嫉俗 - 或者在商业意义上可能是实用的 - 可以为 noSQL 系统提出第三个通用用例(仍然由上述特征/特性集告知):

它更容易上手,任何没有经验(但不是脑残)的 aspring 极客都可以快速上手。这是一个非常强大的功能。(试试用 Oracle ..)

因此,noSQL 系统的用例——通常可以被描述为宽松的持久系统——都是基于实际考虑的最佳信息。

毫无疑问——在可大规模扩展的系统之外——RDBMS 系统是形式上完美的系统,旨在确保数据完整性。


dee*_*see 4

键值存储通常非常快,因此最好将它们用作频繁访问且很少更新的数据的缓存,以减少数据库的负载。

正如您所说,您通常受到查询的限制(尽管MongoDB处理得很好),但键值存储主要用于访问精确数据:用户 X 的个人资料、会话 X 的信息等。

“传统”数据库对于一般网站来说可能绰绰有余,但如果您遇到高负载,键值存储确实可以帮助您缩短加载时间。

编辑:“高负载”是指非常高的负载。键值存储很少需要。

请参阅键值存储的比较。