存储多个ip范围的最佳方式


Best way to store many ip ranges?

我有3000行IP范围,格式如下:

5.9.0.0     5.9.255.255     Hetzner     http://www.hetzner.de/
5.10.64.0   5.10.127.255    SoftLayer   http://www.softlayer.com/
5.34.182.0  5.34.183.255    UA Servers  https://itldc.com/

如果用户访问我的网站,我想查找他们的IP是否在此IP范围内,并在这种情况下阻止他们。用PHP查找IP的最快方法是什么?IP范围是静态的,永远不会改变。

我已经想过创建一个.dat文件来存储IP,这是一个好方法吗?

(以前有一个关于如何在PHP中完成任务的链接。这个问题似乎是关于MySQL的。(

如果只执行IPv4,则存储到数据类型INT UNSIGNED中,存储时使用INET_ATON(),获取时使用INET_NTOA()

对于IPv6,将BINARY(16)INET6_ATON()INET6_NTOA()一起使用。

将虚线四边形转换为整数值只是解决方案的开始。

不能使用普通索引取消引用数组中的值或数据库中的值。考虑一下你想找到一个记录的情况,比如在你的范围内125.54.123.8。如果您的范围由起始地址键入,则只能排除起始地址大于搜索值的记录。如果它位于范围的末尾,则只能排除结束地址小于搜索值的值。您仍然需要检查大约一半的数据才能找到匹配项(或缺少匹配项(。

您可以使用数据桶或嵌套数组,但这些解决方案有些笨拙。

另一个需要注意的问题是,如果你使用php数据结构来管理范围,那么在开始搜索数据集之前,加载和解析数据集所需的时间。根据经验,与从mysql获取记录相比,大约100-200行的数据集会带来这种开销。

解决方案是使用mysql的地理空间功能在一维空间中映射范围——我在适度的硬件上搜索整个互联网指定范围的查找时间低于1ms(使用RIPE、APNIC等的数据集(。

在此处描述了该过程

注意:ip2long((在PHP中返回一个有符号的32位整数值,而MySQL的inet_aton,((是无符号的(即不能混合和匹配这两个函数(