2014-02-18 70 views
0

我有一個很大的產品目錄樹,它目前包含〜36000個類別和〜1千萬個產品(即樹葉)。 (最大深度爲5),它的結構是這樣的:如何在Redis中存儲聚集的目錄樹搜索結果

Cat1 
|_Cat11 
| |_Cat111 
| | |_Cat1111 
| | | |_Product1 
| | | |_... 
| | |_Cat1112 
| | | |_Product1 
| | | |_... 
| | |_Cat1113 
| | | |_Product1 
| | | |_... 
| |_Cat112 
| |_Cat1121 
| | |_Product1 
| | |_... 
| |_Cat1122 
| | |_Product1 
| | |_... 
| |_Cat1123 
|  |_Product1 
|  |_... 
|_Cat12 
| |_Cat121 
| | |_Cat1211 
| | |_Cat1212 
| | |_Cat1213 
| |_Cat122 
| |_Cat1221 
| |_Cat1222 
| |_Cat1223 
|_... 
Cat2 
|... 

當搜索該目錄(使用SQL Server FreeText的搜索),我收到了一堆類別和產品的背面非常快。有些搜索可以獲得很多產品的點擊量。 我希望將結果彙總並顯示當前展開的每個類別的總點擊次數。像這樣(在不同級別2例):

**Ex1 (first level)** 
Cat1(563) 
| 
Cat2(332) 
| 
Cat8(2) 

**Ex2 (second level)** 
Cat1 
|_Cat12(102) 
|_Cat14(201) 
|_... 

我迄今試圖將存儲在Redis的所有父/子關係(存儲爲套)。然後,爲了獲得彙總結果,我簡單地從產品(從搜索結果)到其父母,直到目前擴展的類別(或更確切地說,它的直接子女)遍歷,以找到要呈現的類別並計算匹配的產品數量搜索。如果我在搜索結果中有大約5000種產品,那麼這大約需要20秒。漫長的路要走。

什麼是更好的方法來實現這個目標?一種方法是將所有100萬種產品都彙總到每個類別上,但這需要3600萬個密鑰,並且可能需要大量內存。我目前已經使用500Mb。

+0

你使用lua腳本來做這個搜索嗎?它不會,會有太多的網絡往返,以減慢搜索速度。你應該避免使用'keys'命令來匹配鍵。 – yinqiwen

+0

我使用名爲ServiceStack的c#客戶端進行搜索。我不熟悉lua。它在Redis服務器上運行嗎?如果使用該腳本,我會將整個腳本發送到服務器嗎?我不使用keys命令(我認爲)。我只在客戶端使用「GetSet()」方法。也許它使用引擎蓋下的鑰匙,不知道。爲什麼那麼糟糕,該怎麼做呢? – Thomas

回答

1

如果你想要速度,你應該儘可能地準備在redis中存儲結構或'緩存'。 如果您將產品存儲在HSET中,並在此HSET的「產品數據」成員旁邊添加類別計數器(每個類別一個),則可以使用HINCRBY遞增/遞減計數器。

一般情況下(根據您的需要設計一個Redis緩存):您應該嘗試阻止檢索您不需要的任何數據。

我建議使用Lua script來存儲(/更新/刪除)以及檢索您的彙總報告。 Lua腳本在Redis服務器上執行。 ServiceStack支持它們(SCRIPT LOAD + EVALSHA或簡單地EVAL),你也可以嘗試使用BookSleeve C#客戶端模塊(我們使用它,速度更快一些,'更快':良好的redis數據設計首當其衝)。 BookSleeve C#客戶端專注於多線程的redis pipelining,這可能是您在處理大型數據集時想要的。管道應該也可以用ServiceStack來實現。

如果類別和產品具有整數ID,您還可以將其與ZSET結合使用,您可以在其中使用該ID作爲分數字段。用ZRANGEBYSCORE你可以直接得到'記錄'。 只要您的身份證號碼使用15位或更少,並且不使用'分數'的小數部分,此技術就很安全。因此,ID必須保持在-999999999999999至999999999999999的範圍內。注意:存在這些限制是因爲Redis服務器實際上在內部將分數(浮點數)存儲爲redis字符串表示形式。

希望這可以幫助,TW

+1

謝謝TW。我嘗試了產品哈希方法,它工作的很棒:)現在我只需要創建一個聚合的小lua腳本。 – Thomas

+0

不客氣。聽起來不錯,最後一部分應該是微風:) –