IP地址的快速文件搜索算法

时间:2010-04-18 00:05:08

标签: php algorithm ip-address text-search

问题

查找包含IP地址的文件中是否存在IP地址的最快方法是:

219.93.88.62
219.94.181.87
219.94.193.96
220.1.72.201
220.110.162.50
220.126.52.187
220.126.52.247

约束

  • 没有数据库(例如,MySQL,PostgreSQL,Oracle等)
  • 允许不经常的预处理(参见可能性部分)
  • 很高兴不必为每个查询加载文件(131Kb)
  • 使用5 MB以下的磁盘空间
  • 没有额外的PHP模块

文件详情

  • 每行一个IP地址
  • 9500+行

可能的解决方案

  • 创建目录层次结构(radix tree?)然后使用is_dir()(遗憾的是,这使用87兆字节)

4 个答案:

答案 0 :(得分:3)

由于您的文件已按排序顺序存储IP地址,因此您可以使用二进制搜索在O(log(n))时间内快速找到特定的IP地址。

如果你想进一步提高速度,你可以缓存例如内存中的每100行并首先使用内存中的二进制搜索,然后你就知道需要读入哪个文件来完成搜索。

虽然说131kB确实不是那么多,但最简单和最快速的解决方案是购买更多内存并将整个文件缓存在哈希表的内存中。

答案 1 :(得分:3)

编辑我没有注意到php标记,我不知道该语言是否可以使用以下类型的内容。但无论如何我都会留下这个想法。

IPv4地址可以表示为32位数字,因此我只创建一个int32数组,使用以下Python-ish伪代码将地址转换为'ints`:

x = 0
i = 24
s = '111.222.333.444'
for part in s.split('.'):
    x += part.toint() << i
    i -= 8
IPlist.append(x)

然后你可以获得输入地址,以相同的方式将其转换为int,并对数组进行二进制搜索。

对于~10 k行,数组将需要~40 kBytes。

答案 2 :(得分:3)

如果在到达232.0.17.1

之前要检查9,000个不匹配项,那么逐行扫描文件以查找IP似乎很痛苦

您的文件是否仅限于一个文件?例如让我们说这个列表是被禁止的IP,你只想看看是否有人在列表中。

如果你让DIR包含多个文件怎么办:

BannedIPs
  +- 0.ips
  +- 1.ips
  +- 37.ips
  +- 123.ips
  +- 253.ips
  +- 254.ips

每个文件只包含以该号码开头的IP地址。

如果你足够幸运,甚至可以分发...你有256个文件,但每个只有~37个条目。

因此,当您想要测试:232.0.17.1时,请查看232.ips文件并进行扫描。

答案 3 :(得分:1)

可能不会很快,但我会尝试这样做:如果IP地址文件没有太大变化,请将文件读入数组并缓存(可能是Memcache)并在每次请求时从那里搜索。