【问题标题】:Fast file search algorithm for IP addressesIP 地址的快速文件搜索算法
【发布时间】:2011-02-09 06:34:34
【问题描述】:
问题
如果某个 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 模块
文件详情
可能的解决方案
- 创建目录层次结构 (radix tree?),然后使用
is_dir()(遗憾的是,这使用了 87 兆字节)
【问题讨论】:
标签:
php
algorithm
ip-address
text-search
【解决方案1】:
如果在到达 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 文件并扫描它。
【解决方案2】:
可能不会很快,但我会尝试一下:如果 IP 地址文件没有太大变化,请将文件读入一个数组并缓存它(可能是 Memcache),然后在每个请求上从那里搜索。
【解决方案3】:
编辑 我没有注意到php 标记,我不知道在那种语言中是否可以使用以下类型的东西。但无论如何我都会把它留给这个想法。
IPv4 地址可以表示为 32 位数字,因此我只需创建一个 int32 数组,使用以下 Python 式伪代码将您的地址转换为“整数”:
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。
【解决方案4】:
由于您的文件已经按排序顺序存储了 IP 地址,因此您可以使用二进制搜索在 O(log(n)) 时间内快速找到特定的 IP 地址。
如果您想进一步加快速度,您可以在内存中缓存例如每 100 行并首先使用内存中的二进制搜索,然后您就知道需要读入文件的哪个部分来完成搜索。
话虽如此,131kB真的不算多,所以最简单最快的解决方案就是购买更多的内存,并将整个文件缓存在内存中的哈希表中。