【问题标题】:PHP best way to store many ip ranges?PHP存储许多IP范围的最佳方式?
【发布时间】:2016-12-13 09:17:43
【问题描述】:

我有 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,这是一个好方法吗?

【问题讨论】:

  • postgresql 支持 CIDR 和 INET 数据类型,仅供参考。不知道 mysql 或 sqlite。
  • 我删除了不兼容的数据库标签。请用您正在使用的数据库标记问题,或明确解释为什么它最初用 MySQL 和 SQLite 标记。
  • 最快的方法是一些内存中(在进程之间共享)解决方案,其逻辑针对此特定用途量身定制。对你来说可能是一个巨大的过度杀伤(和不必要的工作)。对您的要求诚实。

标签: php database performance


【解决方案1】:

(之前有一个link是关于如何用PHP做这个任务的,这个问题好像是关于MySQL的。)

如果你只做 IPv4,那么存储到数据类型INT UNSIGNED,存储时使用INET_ATON(),获取时使用INET_NTOA()

对于 IPv6,使用 BINARY(16)INET6_ATON()INET6_NTOA()

【讨论】:

  • 这应该是一条评论。
【解决方案2】:

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

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

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

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

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

流程描述here

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

【讨论】:

    猜你喜欢
    • 2020-10-25
    • 2014-09-03
    • 2013-11-01
    • 1970-01-01
    • 2019-05-20
    • 1970-01-01
    • 1970-01-01
    • 2019-11-04
    • 2013-06-26
    相关资源
    最近更新 更多