2011-08-04 50 views
13

我有點小菜,所以我在這裏...何時使用鍵值存儲進行Web開發?

什麼時候有人會使用鍵值(Redis,memcache等)存儲進行Web開發?一個實際的用例將是最有幫助的。

我的困惑是,一個簡單的數據庫,似乎這麼多的功能,因爲,我的理解,它可以做一切key-value存儲可以做到PLUS它也可以讓你做過濾/查詢。意思是,我的理解,你不能做到像過濾器:select * homes where price > 100000用key-value存儲。

UPDATE

讓我們把這個例子更真實。假設StackOverflow使用鍵值存儲(memcache,redis等)。

如何將一個key-value存儲幫助好處託管#1的需求?

+1

敢肯定你可以做鍵值存儲的過濾器,如果你想 - 部分取決於商店的執行,也許在你自己的聰明才智。 –

回答

3

鍵值存儲通常是非常快,因此是件好事,他們作爲被頻繁訪問,也很少更新,以減少對您的DB負載數據的高速緩存。

正如你所說,你通常與查詢的限制(儘管MongoDB處理它們相當不錯),但鍵值存儲大多意味着訪問精確的數據:用戶X的個人資料,話X的信息等

「傳統」的數據庫可能會是綽綽有餘對於一般網站多,但如果遇到高負載鍵值存儲可以真正幫助您的加載時間。

編輯:而「高負荷」,我的意思是真的高負荷。關鍵價值商店很少需要。

See this comparison of key-value stores.

+0

感謝您的鏈接,直到很有幫助。 –

+0

你的答案仍然適用,如果你有一個1000個項目和每個項目8個字符串字段,需要刷新每20秒,並將通過模糊搜索鍵訪問JSON數組? – PirateApp

5

不要像memcached的(這是不打算永久存儲數據)混淆的NoSQL數據庫類型。

memcached的典型用途是存儲可以通過Web服務器集羣來訪問一些查詢結果 - 即。共享緩存。例如。在這個頁面上是一個相關文章的列表,數據庫可能有一些工作要做,以產生該列表。如果每次有人加載頁面時都這樣做,那麼您將爲數據庫創建大量工作。相反,第一次檢索到的結果可以存儲在memcached服務器上,其中鍵爲頁面ID。然後,任何集羣中的Web服務器可以非常迅速地獲取信息,而不必經常訪問數據庫。一段時間後,緩存條目將被memcached清除,以便舊文章的結果不會佔用空間。 [免責聲明:我不知道如果StackOverflow實際上這樣做]。

A「的NoSQL」,另一方面數據庫是用於永久存儲信息。如果你的數據模式非常簡單,查詢也是如此,那麼它可能比標準的SQL數據庫更快。許多Web應用程序並不需要非常複雜的數據庫等NoSQL數據庫可以是一個不錯的選擇。

+0

爲什麼不直接緩存整個頁面呢? – Jacjoi

+0

您可以緩存部分頁面,但不是全部,因爲(例如)它的我的登錄名稱位於我的版本頂部。但這是一個公平的觀點 - 你可以將其中很多緩存爲HTML片段。 –

1

只是一個增加bstrawson的回答, 「MEM-緩存 -d」是一個緩存機制,而Redis是一個永久的存儲,但都存儲數據作爲鍵值對。

在鍵值存儲搜索(像Redis的或Membase的)更像搜索所有價值在關係數據庫中,太慢了。如果你想做一些查詢,你可能需要移動到面向文檔的NoSQL類型DB,比如MongoDB或CouchDB,你可以做一些查詢部分。

不久的將來,你將能夠處理couchbase斷絕2.0將解決與新推出的UnQL和緩存(從memcached的源代碼中直接導出)NoSQL數據查詢所有的緊迫問題

3

一般有兩種可行的使用-cases爲NOSQL:

  1. 快速應用程序開發
  2. 大規模可擴展的系統

事實上,大多數noSQL解決方案都是無效的模式;要求的儀式要少得多;重量輕(API方面);並且與更規範的關係持久性系統相比,提供顯着的性能增益,以通知它們適用於上述2個用例(在一般意義上)。

憤世嫉俗 - 或在商業意義也許現實 - 一個可以提出第三個一般使用情況下的NoSQL系統(仍然由上述特性組獲悉/功能):

這是比較容易grock和任何缺乏經驗(但無腦死亡)的aspring怪胎都可以輕鬆撿起它。這是一個非常強大的功能。 (嘗試與甲骨文..)

所以,NoSQL系統的使用情況 - 這在一般的可以被定性爲寬鬆持久系統 - 都通過最佳實踐考慮通知。

除了龐大的可擴展系統外,絕對沒有任何問題 - RDBMS系統是旨在確保數據完整性的正式完美系統。

0

堆棧溢出確實使用Redis和廣泛的。詳細回答你的問題,以Stack Overflow爲例,a couple of niceblog posts by @Mark Gravell。 Mark是完全異步的.NET Redis綁定庫的作者。

11

我無法回答何時使用鍵值(此處爲kv)數據存儲的問題,但我可以向您展示一些示例,並回答您的stackoverflow示例。

有了數據庫訪問,大部分你需要的是一個kv商店。例如,用戶使用用戶名「joe」登錄。所以你在你的數據庫中查找「user:joe」並檢索他的密碼(當然是散列)。或者,也許你在「user:pass:joe」下有他的密碼,那真的沒關係。如果它是堆棧溢出並且您正在渲染頁面http://stackoverflow.com/questions/6935566/when-to-use-a-key-value-store-for-web-development,則會查找「question:6935566」並使用它。很容易看出kv商店如何解決你的大部分問題。

我想說kv商店是傳統RDMS提供的功能的一個子集。這是因爲傳統RDMS的設計提供了許多縮放問題,並且在縮放時通常會丟失功能。 KV商店不會提供這些功能,所以它們不會限制您。但是,這些功能通常可以創建,無論從核心設計還是可擴展的(因爲如果不是這些功能就顯而易見)。

但是,這並不意味着有些事情是你無法做到的。例如你提到查詢。這是許多KV商店的陷阱,因爲它們通常不知道價值(不總是正確的,例如,redis和更多),並且無法找到您正在尋找的東西。更糟糕的是,它們並不是設計得很快,它們只是快速地按鍵快速查找。

解決此問題的一個辦法是按照字典順序對鍵進行排序並允許範圍查詢。這基本上是「在問題1和問題5之間給我一切」。現在這個例子相當無用,但是範圍查詢有很多用途。

你說你想要所有的房子超過100000美元。如果你想能夠做到這一點,你會創建一個房價指數。假設你有下列房屋。

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"}] 

但如果你有範圍查詢(通常稱爲keyscans),你可以創建這樣一個指標:

house:index:price:040000 -> 2 
house:index:price:110000 -> 3 
house:index:price:150000 -> 1 
house:index:price:500000 -> 0 

然後你可以要求house:index:price:100000house:index:price::(之間的鍵「:」字符是'9'後的字符),你會得到[3,1,0],這是所有的房子比$ 100 000更昂貴(他們也有幫助)。另一個好處就是它們可能位於羣集的一個「分區」上,因此這個查詢將與單獨獲取的時間大致相同(加上額外的傳輸開銷),或者如果您的範圍恰好超過一個服務器邊界(但這些可以並行完成!)。

這樣就顯示瞭如何在kv商店中查詢。你可以查詢任何可以作爲字符串排序的東西(幾乎任何東西),並很快查找它。如果你沒有範圍查詢,你需要將你的整個索引存儲在一個很糟糕的密鑰下,但是如果你有範圍查詢,它是非常好的,而且速度非常快。這是一個更復雜的例子。

我想要多倫多的房屋價格低於100000美元。我只需要設計我的索引。 (我在一些房屋中增加了它,使它更有意義)起初以爲你可能會爲每個房產建立另一個索引,但你很快就會意識到這意味着你必須選擇每個未售出的房子並從數據庫中下載它。 (當我說縮放問題立刻就很明顯時,這就是我的意思。)解決方案是使用多索引。一旦建成,你可以選擇你想要的值。

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   -> "" 

現在,不像最後一個例子,我把id放在關鍵字中。這允許兩個房屋具有相同的屬性。我可以將它們合併到值中,但添加刪除索引變得更加困難。我還選擇將我的數據與~分開。這是因爲它在所有字母后按字母順序排列,確保全名將被排序,並且我不必爲每個城市填充相同的長度。在生產系統中,我可能會使用字節255或0。

現在範圍house:index:sold:city:price:f~Toronto~100000 - house:index:sold:city:price:f~Toronto~~將選擇與查詢匹配的所有房屋。重要的是要注意的是,查詢與結果的數量呈線性關係。這確實意味着你必須爲你想索引的每一組屬性建立索引(儘管我們的例子中的索引也適用於已售出和已售出的城市查詢)。這可能看起來像很多工作,但最終你意識到只是你在做,而不是你的數據庫。我敢肯定,我們將開始看到庫這種事情很快出來了:d

拉伸的話題了一下後,我已經表明:

  • 一個千伏商店的一些應用。
  • 如何在kv商店中查詢。

我認爲你會發現,KV-商店足以讓許多應用往往可以提供更好的性能和可用性比傳統的關係數據庫管理系統。這就是說,每個應用程序是不同的,因此,不可能回答原來的問題。