大规模IP地址黑名单高性能查询实现
嗯……前阵子接了个活儿,需要做一个基于IP地址黑名单的分流网关。刚接到的时候心想iptables不就行了么,没想到一看客户给的IP黑名单规模……我擦……上亿个……
黑名单到了这个规模,就不得不考虑下优化的问题了。要知道从0.0.0.0到255.255.255.255,IP地址总共也只有232个,约43亿,除去不可能用于实际的地址以及内网地址之后就更少了,只有几分之一。上亿个IP地址的黑名单已经达到实际可用IP地址的几分之一了,而且还要实现大流量高性能查询,实在是……
最初打算是用redis来实现,而第一版程序也是这么实现的,不过可能是不熟悉redis,做出来的东西性能不够达标。
然后我想到一个点子……
技术需求如下:
IP地址由4个字节构成,从0.0.0.0到255.255.255.255,每个IP地址在网关只有两种状态:在/不在黑名单里。上面已经说过,IP地址由4个字节构成。那么我只需要构建一个232规模的字节数组,完成全IP地址到本地内存空间的映射。每个字节只存0或者1,表示对应的IP地址是不是黑名单IP即可。这么做需要4GB的内存。
进一步考虑,一个字节只存一个bool实在是太浪费,对这种映射关系稍做修改,每个IP地址对应到字节数组里一个字节的某个二进制位即可,这样就能把数据压缩到原先的八分之一,即512MB。这样32位的系统也可以胜任了(虽然提供的是64位系统)。
使用数据库技术,绕不过去的是查询和排序之类耗时的工作,对于如此庞大的黑名单库(其规模已经达到全IP地址数的几分之一),这是主要的性能消耗。但如果将IP地址映射到本地内存空间,那么直接就省掉了这个最消耗性能的操作,直接就能查到这个IP在不在黑名单里了。
好了,想法有了,实现起来也就是五分钟的事儿,我编写的版本如下(C实现,省略了由IP地址字符串转换成无符号32位整数的过程):
#include "stdio.h"
#include "stdlib.h"
#include "string.h" #define BLACKLIST_FILE "d:\\dummy_ip.bin"//一个512MB大小的随机内容的二进制文件 char *test=new char[**];//IP地址映射到本地内存数据的数组
int init();
bool checkBlackList(unsigned long inputIP);
void setValue(unsigned long inputIP, bool inputValue); //全IP段IP黑名单快速查询 //原理:IP从0.0.0.0到255.255.255.255,总共2^32个IP地址。每个IP地址只有两个状态:在黑名单,或者不在
//因此最初设计是申请0x00000000到0xFFFFFFFF个字节的内存空间(4GB),建立全IP地址到内存的映射,每个字节存放一个二进位,存储该地址对应IP是不是黑名单IP
//经过压缩之后,每个字节存放8个二进制位,因此总空间可压缩到原先的八分之一,即512MB
//查询时,将IP地址的四个字节合组成一个int32并右移3位,得到该IP对应的字节,然后用这个int32的低三位确定字节里的二进制位,即是否是黑名单IP
//将IP转换成int32之后,单次查询仅需要1次内存直接访问和3次位操作
//适用于IP黑名单很大的情况 int main(int argc, char* argv[])
{
init();
for(int i=;i<;++i)
{ //生成随机的IP地址进行查询
unsigned char a=rand()%,b=rand()%,c=rand()%,d=rand()%;
unsigned long ip=a*b*c*d;
printf("IP:%u.%u.%u.%u is hit:%d\n",a,b,c,d,checkBlackList(ip));
}
return ;
} //数据初始化,将保存在本地文件的数据读取到内存里
int init()
{
FILE* fp = fopen(BLACKLIST_FILE,"r");
if (fp==NULL)
return ;
fgets(test,strlen(test),fp);
fclose(fp);
return ;
} //查询IP是否在黑名单里,仅仅需要三次位运算和一次内存访问
bool checkBlackList(unsigned long inputIP)
{
return test[inputIP>>] &(<<(inputIP & (unsigned long)));
} //设置黑名单IP的值。找到IP对应的字节,然后使用掩码和位运算设置对应的二进制位的值
void setValue(unsigned long inputIP, bool inputValue)
{
unsigned long byteIndex = inputIP >> ;
char maskByte = (char)(<<(inputIP & (unsigned long)));
test[byteIndex] = (inputValue?(test[byteIndex] | maskByte):(test[byteIndex] & (!maskByte)));
/*if(inputValue)//喜欢简洁,改成(:?)形式了,见上行
test[byteIndex] = test[byteIndex] | maskByte;
else
test[byteIndex] = test[byteIndex] & (!maskByte);*/
}
嗯,跑起来可比之前的redis实现快了不是一星半点。
大规模IP地址黑名单高性能查询实现的更多相关文章
- Python实现IP地址归属地查询
一.使用淘宝IP地址库查询 使用淘宝的Rest API,可以快速查询IP地址的归属地: 图00-淘宝IP地址库RestAPI使用说明 图01-使用淘宝免费IP地址库-查询IP归属地 存在问题:淘宝的免 ...
- IP地址归属地查询
http://www.ipip.net/download.html#ip_code 下载免费版 IP 地址数据库. 网站下面有官方给出的查找IP地址所属国家.省.市的办法. python版本列出 py ...
- Trie树的应用:查询IP地址的ISP
1. 问题描述 给定一个IP地址,如何查询其所属的ISP,如:中国移动(ChinaMobile),中国电信(ChinaTelecom),中国铁通(ChinaTietong)?现有ISP的IP地址区段可 ...
- 手机归属地查询-IP地址查询-身份证查询-域名备案查询--Api接口
使用这些接口是需要密钥的 公共密钥 appkey: 10003 secret: d1149a30182aa2088ef645309ea193bf 生成后sign: b59bc3ef6191eb9f ...
- 黄聪:分享几个免费IP地址查询接口(API)
淘宝IP地址库 提供的服务包括:1. 根据用户提供的IP地址,快速查询出该IP地址所在的地理信息和地理相关的信息,包括国家.省.市和运营商.2. 用户可以根据自己所在的位置和使用的IP地址更新我们的服 ...
- 通过Web Service实现IP地址查询功能
实例01 实现一个简单的Web服务访问 本实例将实现IP地址查询接口服务,根据用户传入的IP地址返回IP所在的省.市.地区,实例中将会用到IP地址库用于查询信息,由于数据较多,所以读者可在光盘资源文件 ...
- 分享几个免费IP地址查询接口(API)
淘宝IP地址库 提供的服务包括:1. 根据用户提供的IP地址,快速查询出该IP地址所在的地理信息和地理相关的信息,包括国家.省.市和运营商.2. 用户可以根据自己所在的位置和使用的IP地址更新我们的服 ...
- 虚拟机下CentOS 配置IP地址的三种方法
1.自动获取IP地址(我不是用的这种方法,不做过多介绍) 虚拟机使用桥接模式,相当于连接到物理机的网络里,物理机网络有DHCP服务器自动分配IP地址. #dhclient 自动获取ip地址命令 #if ...
- 虚拟机下CentOS 6.5配置IP地址的三种方法
实验软件环境:虚拟机Vmware Workstation10.0 .CentOS 6.5 32位 1.自动获取IP地址 虚拟机使用桥接模式,相当于连接到物理机的网络里,物理机网络有DHCP服务器自动分 ...
随机推荐
- 关于 escape、encodeURI、encodeURIComponent
参考资料:http://hi.baidu.com/flondon/item/983b3af35b83fa13ce9f3291 http://www.w3school.com.cn/js/jsref ...
- bootstrap-datetime 的使用
bootstrap-datetime js的下载 http://pan.baidu.com/s/1eQnE5dK html的代码 <div class="input-group dat ...
- SQL EXEC 命令用法
EXEC命令有两个用法: 1.执行一个存储过程,或者执行一个动态批次. 2.批次是一个内容为SQL语句的字符串. 举列子: 1.exec name_proc :没有参数 exec name_proc ...
- 11.12模拟考T1(可持续优化)PS:神奇的东西
1.数列操作 (array.pas/c/cpp) [问题描述] 现在有一个数列,最初包含0个数.现在要对数列操作n次,操作有3类. 1) a k,在数列的最后插入一个整数k 2) s 将最近插入的 ...
- outscan 一键批量 get struct2 devMode (CNVD-2016-04656)
之前写的一个玩意 下载地址:http://pan.baidu.com/s/1i5jmEwP 密码:v8v3 一键批量 get struct2 devMode 支持百度.google(google有访问 ...
- BSD License
BSD开源协议(original BSD license.FreeBSD license.Original BSD license) BSD开源协议是一个给于使用者很大自由的协议.基本上使用者可以”为 ...
- ACM water
1000 纯属适应题 1003 做的时候花了很久,现在看好像也不难 1004 适应题,求下平均就行 1005 要读懂题就行 1007 逆序数,discuss方法 1046 全部暴搜一遍.. ...
- 使用subclass UIActivity的方案来分享图片
IOS6开始, 系统提供了UIActivityViewController, 对图片,文字,url进行相关的操作. 对于缺乏UI设计师的开发来说, 使用它进行轻量级的分享是很好的选择. 最大的缺点是自 ...
- MSXML应用总结
MSXML的DOM模型是符合W3C DOM标准的,而DOM API在Windows中以COM接口的形式提供,关于COM请大家查阅相关资料.简单来说,COM提供了一个环境和一套规则,使接口的设计实现到对 ...
- (转)LSTM NEURAL NETWORK FOR TIME SERIES PREDICTION
LSTM NEURAL NETWORK FOR TIME SERIES PREDICTION Wed 21st Dec 2016 Neural Networks these days are th ...