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

时间:2016-08-07 14:10:24

标签: php database performance

我有这种格式的3,000行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这是一个好方法吗?

2 个答案:

答案 0 :(得分:0)

(之前有一个link如何在PHP中完成任务。这个问题似乎与MySQL有关。)

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

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

答案 1 :(得分:0)

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

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

你可以使用数据手册或嵌套数组,但这些都是有点愚蠢的解决方案。

如果您使用php数据结构来管理范围,则需要进一步考虑的是在开始搜索数据集之前加载和解析数据集所需的时间。根据经验,与从mysql获取记录相比,这一开销与大约100-200行的数据集相关。

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

该过程描述为here

注意:ip2long()在PHP中返回一个带符号的32位整数值,而MySQL的inet_aton,()是无符号的(即你可以&#t; tmix并匹配这两个函数)