【问题标题】:Given a list of ranges how can we find if the given value exist in that list of ranges in node js给定一个范围列表,我们如何找到给定值是否存在于节点 js 的该范围列表中
【发布时间】:2017-09-13 17:24:49
【问题描述】:

我有一组 ip 范围,我需要查找用户给定的 ip 是否存在于给定的 ip 范围列表之间。

这是这个问题的延续

How to check if a given ip falls between a given ip range using node js

Jonas 帮助我获取了该 ip 是否存在。但我不想进行详尽的迭代搜索,我想进行快速的性能密集型搜索,因为我的 ip 范围(或数字范围)列表会很大。

我研究了 jonas 指出的布隆过滤器,但我不相信布隆过滤器可能会有所帮助。我也在看Interval Tree 但我不认为它可以搜索间隔它需要间隔作为输入。

我的ip列表范围https://github.com/client9/ipcat/blob/master/datacenters.csv#L4

如何快速搜索。我正在使用节点 js

【问题讨论】:

  • 线性比较有什么问题?除非你有超过 100 万个范围,否则不应该是一个大问题
  • @juvian 只是承认它是一个广告服务器黑名单 ips,在这里我需要在几毫秒内完成它,数据将被添加到这里,即未来更多的 ip 范围。还有其他与广告投放相关的流程,所以这需要快速
  • 可以有多个匹配项吗?
  • 不,它应该发生,我只需要给出一个真假,它是否存在于ip范围内而不是
  • 如果它们是非重叠范围,您可以将它们转换为数字范围,保持排序,然后可以在 log n 比较中进行每个查询,但您需要将所有查询都保存在内存中

标签: javascript node.js intervals interval-tree


【解决方案1】:

我观察到您的许多 ip 看起来像这样:

123.123.123.0 - 123.123.123.255

所以要过滤掉它们,我们只需要阻止每个 ip 开头:

123.123.123

现在只剩下 16E6 个 IP 范围被阻止。但是,您可能只会阻止其中的一些,这使我们能够将其存储在 Set 中。一段代码:

const blockedRange = new Set();

function IPtoBlock(ip){
   return ip.split(".").slice(0,3).join(".");
}

//to block an ip range ( if youve got one ip of it):
blockedRange.add( IPtoBlock("192.168.2.48") );

//to check for an ip
blockedRange.has( IPtoBlock( someip ));

所以现在只有几个范围不是块,例如:

 5.44.26.144 - 5.44.26.159

但是,嘿,只有 15 个 ip,我们可以将其添加到禁止 ip 列表中:

const blockedIPs = new Set();

function NumtoIP(num){
  return (num+"").split("").reduce((res,char,i) =>
    res + (!i || i%3?"":".") + (char === "0"?"":char)
  ,"");
 }

function addRange(start,end){
 start = IPtoNum(start);
 end = IPtoNum(end);//include from last answer
 for(var i = start; i <= end; i++){
   blockedIPs.add( NumtoIP( i ) );
 }
}

所以当迭代我们的范围列表时,我们可以分开:

ranges.forEach(([min,max]) => {
  if( min.substr(-1) === "0" && max.substr(-3) === "255" ){
      blockedRange.add( IPtoBlock( min ) );
  }else{
      addRange(min, max);
  }
});

检查一个ip是否失败

function isBlocked(ip){
  return blockedIPs.has(ip) && blockedRange.has( IPtoBlock(ip) );
 }

【讨论】:

  • 所以你建议先分离数据?然后手动添加每个ip
  • 5.10.64.05.10.127.255这样的ip怎么样,这个解决方案是不可行的
  • @infosys 很好,只有 63 个块 ... ;)
  • 哈哈,但我不认为这不符合您通常的标准,就像之前的答案:P
  • @infosys 我的第一个答案很慢但很小,这个很快但可能会消耗一些 RAM(可以提取到 redis 或类似的东西)
猜你喜欢
  • 2019-01-13
  • 1970-01-01
  • 1970-01-01
  • 2010-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-22
  • 1970-01-01
相关资源
最近更新 更多