如何在Redis中存储聚合目录树搜索结果

时间:2014-02-18 20:52:17

标签: redis

我有一个很大的产品目录树,目前包含~36,000个类别和~1百万个产品(即叶子)。它的结构如下(最大深度为5):

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万个密钥,并且可能需要大量的RAM。我目前已经使用了500Mb。

1 个答案:

答案 0 :(得分:1)

如果你想要速度,你应该尽可能多地准备在redis中存储结构或'缓存'。 如果您将产品存储在HSET中,并在此HSET中的“产品数据”成员旁添加类别计数器(每个类别一个),则可以使用HINCRBY递增/递减柜台。

一般情况下(根据需要设计Redis缓存):您应该尝试阻止检索任何不需要的数据。

我建议使用Lua script来存储(/更新/删除)以及检索汇总的报告。 Lua脚本在Redis服务器上执行。 ServiceStack支持它们(SCRIPT LOAD + EVALSHA或简称EVAL),您也可以尝试BookSleeve C#客户端模块(我们使用它,并且速度更快。'更快':良好的redis-data设计首先出现。 BookSleeve C#客户端专注于多线程redis pipelining,这可能是您处理大型数据集时的需求。也可以使用ServiceStack进行流水线操作。

如果类别和产品具有整数ID,您还可以将其与ZSET结合使用,您可以将ID用作分数字段。使用ZRANGEBYSCORE,您可以直接获取“记录”。 只要您的ID使用15位数或更少,并且不使用“得分”的小数部分,此技术就是安全的。所以ID必须保持在-999999999999999到999999999999999的范围内。注意:存在这些限制是因为Redis服务器实际上将得分(浮点数)内部存储为redis-string表示。

希望这有帮助,TW