0

我正在为一个尚未设置约束和规范的新项目做一些研究。需要的一件事是直接在根域下的大量路径。这可能会增加数百万条路径。这些路径没有共同的结构或独特的部分,所以我必须寻找完全匹配的东西。

现在我知道分解这些路径更有效,这也有助于路径查找。但是我正在研究这里的可能性,所以请耐心等待。

我正在评估实现这一目标的方法,同时保持出色的性能。我想到了以下方法:

  • 将路径存储在 SQL 数据库中并对每个请求进行查找。这似乎是最糟糕的选择,绝对不会被使用。
  • 将路径存储在 Redis 等键值存储中。这会好很多,而且我认为表现得很好(尽管必须对其进行基准测试)。
  • 进行字符串/正则表达式匹配 - 就像许多框架一样,开箱即用 - 因为这么多可能的匹配是疯狂的,因此不是一个真正的选择。但是我可以看到,在结合一些智能优化的情况下,逐字母比较的某种算法是如何起作用的。

但也许有一些我不知道的工具/方法更适合这类问题。不过,我可以使用任何提示来完成此操作。

哦,如果有人想知道,不,这不是家庭作业。


更新

我已经测试了 Redis 方法。基于两组关键词,我得到了 1.5 亿条路径。我已经使用set命令添加了它们中的每一个,其值是一个序列化的 id 字符串,我可以使用它来识别请求中的实际关键字。( SET 'keyword1-keyword2' '<serialized_string>')

在具有一百万条记录的数据集的本地 VM 中进行快速测试返回了有希望的结果:对 1000 个请求进行基准测试平均需要 2 毫秒。这是在我的笔记本电脑上,它运行着很多其他的东西。

接下来我在一个 4 核 8GB 内存的 VPS 上做了一个完整的测试,完整的 1.5 亿条记录。这产生了一个文件大小为 3.1G 的数据库和大约 9GB 的内存。由于数据库无法完全加载到内存中,Redis 开始交换,这导致了可怕的结果:平均大约 100 毫秒。

显然这不会起作用并且可以很好地扩展。要么每个 Web 服务器都需要有大量的 RAM,要么我们必须使用专用的 Redis 路由服务器。我读过Instagram 工程师的一篇文章,他们想出了一个技巧来显着减小数据库大小,但我还没有尝试过。无论哪种方式,这似乎都不是正确的方法。回到绘图板。

4

3 回答 3

1

我认为 Redis 是你最好的选择。SQL 会很慢,根据我的经验,正则表达式在查询中总是非常缓慢。

我将执行以下步骤来测试 Redis:

  1. 使用本地 VM 或在 EC2 之类的云中启动 Redis 实例。
  2. 下载一两个字典并将这些数据泵入 Redis。例如这里的一些东西:http : //wordlist.sourceforge.net/ 确保你规范化数据。例如,始终将字符串小写并删除字符串开头/结尾处的空格等。
  3. 我会忽略哈希。我看不出您需要对 URL 进行哈希处理的原因?如果您想调试东西并且它似乎没有“购买”您任何东西,那么以后就不可能阅读。我去了http://www.sha1-online.com/,然后输入ryan并获得ea3cd978650417470535f3a4725b6b5042a6ab59了哈希值。将原始文本放入 RAM 中会小得多,这将有助于 Redis。显然,对于更长的路径,散列会更好,但是您的示例非常小。=)
  4. 编写一个从 Redis 读取的工具,看看它的性能如何。
  5. 利润!

请记住,Redis 需要将整个数据集保存在 RAM 中,因此请进行相应的计划。

于 2013-04-23T23:36:21.217 回答
1

将路径存储在 SQL 数据库中并对每个请求进行查找。这似乎是最糟糕的选择,绝对不会被使用。

您可能低估了数据库的功能。我可以邀请你重新考虑你在那里的立场吗?

对于 Postgres(或带有 InnoDB 的 MySQL),一百万个条目比微小的要高出一个档次。将整个路径存储在一个字段中,在其上添加索引,清理,分析。在您确定关键对象的 ID 之前,不要进行疯狂的连接,并且您在查找速度方面会很好。从 psql 运行查询时说几毫秒。

如果您获得大量流量,您真正的问题将是与磁盘 IO 相关的瓶颈。这里的经营座右铭是:越少越好。除了在您的 php 服务器上安装 APC、如果您使用 Ruby 则使用Passenger等基础知识之外:

  1. 确保服务器有足够的 RAM 来适应该索引。

  2. 缓存对与 memcached 中每个路径相关的对象的引用。

  3. 如果您可以在十几个正则表达式中对所有路由进行分类,那么它们可能会有所帮助,因为它们允许使用更小、更有针对性的索引,这些索引更容易保存在内存中。如果没有,只需坚持存储(可能是尾部斜线)整个路径并继续前进。

  4. 担心错过。如果您有一个重定向到规范 URL 的非规范 URL,请将重定向存储在 memcached 中,没有任何到期日期,然后继续使用它。

  5. 我提到了很多 RAM 和 memcached 吗?

  6. 哦,也不要高估您正在使用的 ORM。构建查询所花费的时间可能比数据存储解析、检索和返回结果所花费的时间更多。

  7. 内存...内存缓存...

老实说,Reddis 与 SQL + memcached 选项没有太大区别,除了在内存管理(如您所见)、分片、复制和语法方面。当然,还有熟悉。

您的关键决策点(除了不包括迭代多个正则表达式)应该是您的数据的结构。如果它是高度结构化的,对原子性有关键需求,SQL + memcached 应该是你的首选。如果您的自定义字段遍布且 EAV 表过于庞大,那么使用 Reddis 或 CouchDB 或其他 NoSQL 存储应该在您的雷达上。

在任何一种情况下,拥有大量RAM 来将这些索引保存在内存中都会有所帮助,并且如果您需要扩展,那么整个事物前面的 memcached 集群将永远不会受到伤害。

于 2013-04-24T17:10:56.843 回答
0

我建议使用某种键值存储(即散列存储),可能与散列键一起使用,使其更短(恕我直言,SHA-1 之类的就可以了)。

于 2013-04-19T19:58:59.700 回答