如何使用其他一些数据存储区实现Redis的功能?

时间:2013-01-30 20:59:07

标签: perl nosql full-text-search redis

我发现Redis对我的项目有很好的功能(webapp的自动完成后端)。基本上,它是我的全文搜索引擎。现在我正在寻找Redis的替代品,因为我无法将整个数据集保存在内存中。

我像这样创建我的Redis商店(找不到这个想法的信用链接):

  1. 我将常规数据库中的(加权)项目分成每个字符后的3个字符块(“单词” - > ['wor', 'ord', 'rds']
  2. 每个块都成为一个键,用于保存具有此类块的项目ID的已排序列表。 (ZADD chunk weight items_id
  3. 每个项目ID也是关于项目(SET items_id items_hash_in_json
  4. 的一些简单JSON文档的关键

    搜索的工作原理如下:

    1. 查询字符串与3个字符串块相同
    2. 我询问所有这些块的交集并获取items_id-s列表(ZINTERSTOREZRANGEBYSCORE的组合)
    3. 按items_id-s
    4. 返回JSON文档列表

      简单明了。非常有效和快速。在这样的流程中仍有一些较小的缺点,但大多数情况下我觉得我的域名拥有恰当的工具和正确的数据类型。

      主要问题是:它需要太多内存。我在数据库中有大约600K项目,并且在'索引'后我将它们在40个字符后减少,但它仍需要2.5GB RAM。这项任务有点多了。数据集会增长,但不会太快和太快,但仍然存在。

      我现在看了一些NoSQL商店,我没有像Redis那样遇到类似的方法和工具。也许这是因为我现在看起来每件作品的锤子,但我觉得与其他NoSQL商店我需要实现自己这样的功能(排序列表,找到它们的交集,简单的键值作为二进制字符串,插入数据死简单,简单协议/ API和简单客户端。)

      我也想要Perl绑定,但是如果协议非常简单(如CoachDB的REST),则不是强制性的。

      您是否知道使用其他NoSQL产品实现我的解决方案的工具?

      另一方面,我已经寻找完全不同的解决方案(如couchdb-lucene,但我想避免放弃上面描述的系统。

2 个答案:

答案 0 :(得分:1)

HTTP缓存 我有一个可能的解决方案,我目前在我的网站上使用。我使用Nginx缓存自动完成查询与静态文件。 Nginx可以非常快速地提供静态文件。这是我在配置中的示例行。

http {

    fastcgi_cache_path /var/cache/nginx levels=1:2
            keys_zone=tt:600m
            inactive=7d max_size=10g;

    fastcgi_temp_path /var/cache/nginx/tmp;

}

此块描述了存储文件的路径。 level是多少目录深,1:2就足够了。我的区域名为tt,无论你想要什么,都可以命名。随后是到期时间。

location ~ /tt/(.+)\.php$ {
            try_files $uri /index.php?$args;
            fastcgi_index   index.php;
            fastcgi_pass    127.0.0.1:9000;
            include         fastcgi_params;
            fastcgi_param   SCRIPT_FILENAME    $document_root$fastcgi_script_name;
            fastcgi_param   SCRIPT_NAME        $fastcgi_script_name;

                #Caching parameters
                fastcgi_cache tt;

                fastcgi_cache_key "$scheme$request_method$host$request_uri";

                fastcgi_cache_valid  200 302 304 30m;
                fastcgi_cache_valid  301 1h;
                fastcgi_cache_valid  any 5m;
                fastcgi_cache_use_stale error timeout invalid_header updating http_500;
        }

位置块将包含缓存参数。因此,任何带有URI /tt/.*.php的内容都将被缓存。 URI +查询字符串将成为缓存键。

如果您不使用Nginx,相同的概念可能适用于其他网络服务器。我希望这会有所帮助。

修改

来自评论: 使用index作为普通文件似乎比SQL查询慢。不过,我还没有对它们进行基准测试。

Nginx的缓存命中将如下所示:

  

- > Nginx - >文件

小姐:

  

- > Nginx - > php / python / ruby​​ - >分贝(redis的/ MySQL的/其他)

第一条路径可能看起来比较慢,因为您会想到diskio,但事实并非如此,操作系统会自动缓存经常访问的文件。因此,当Nginx升温时,只需点击你的PHP后端说“Hello world”就会比较慢。我提出这个主张是因为它就像提供静态文件一样。

实际命中/未命中率取决于应用程序,数据和配置。根据我的经验,人们使用了很多相同的搜索词,所以你可能不会有600k文件。即使你这样做并没有真正受到伤害,Nginx会为你管理它们。如果您的数据发生很大变化并且您希望搜索能够快速反映这些变化,则此方法不是很好。你必须设置一个短暂的过期时间,这会导致更多的失误。

Redis Zip Lists / Hashes http://redis.io/topics/memory-optimization

如果您仍需要排序集,请确保链接中的配置设置设置得足够高,以满足您的数据集需求。如果您能够使用哈希值,则可以使用在该页面上显示较低的算法来节省大量内存。我认为你可以在将item_id链接到json字符串时使用它。

答案 1 :(得分:0)

只是简单的想法可能对你有用。它不是您问题的直接和准确答案。

我认为您的大部分数据或重要部分都位于这些JSON文档中。在这种情况下,我建议您稍微改变一下您的数据基础架构:为了保留Redis的所有好处,您应该使用相同的前两个步骤进行创建搜索,但改变你的第三步。不要使用Redis来存储这些JSON文档,只需将它们移动到您喜欢/使用过的数据库的简单索引表即可。这样您只需处理块和密钥并执行Redis提供的操作,但在步骤3中,您将获取item_id列表并从数据库中检索JSON数据。可能SELECT ... WHERE item_id IN(...)就足够了。