看到很多网站提供IP地址查询的服务,当时就想如此庞大的IP数据库,如何做才能做到适合互联网的高并发呢?
后来在网上突然发现了有些网友发布的全球IP数据库包,下下来也不大,文本文件有10多M,大约有36W+数据,然后看了看文件的格式,就想把他导入数据库看看,然后利用数据库简单的查了查我们所在地的IP地址信息是否准确,效率还挺高,0.00s就出结果了,然后我就用随机生成ip地址的方式进行测试,发现每秒也就查询200~500次,这个时候MySQL符合已经很重。这样肯定不行啊,对于大量的互联网请求根本无法满足,如果是集群对于这种小的程序又没有必要。
然后就又想到了文件,然后利用找到的原始文件,然后对里面的格式进行了调整,准备使用Java的RandomAccessFile对文件直接查找,由于IP地址信息是按照顺序进行排序的,所以我把所有的ip转换成了int类型,然后利用二分法进行查找
public String search(String ip) {
RandomAccessFile raf = new RandomAccessFile("E:/aa/city/ips.txt", "r");
long seek = IPConvert.IP2Long(ip);
int index = 0;
int start = 0;
int end = 25133;
String address = null;
IpA ipa;
while (true) {
try {
index = start + ((end - start) / 2);
raf.position(index * 56);
ipa = new IpA();
ipa.setFromip(readFromip(mbb));
ipa.setToip(readToip(mbb));
if (ipa.getFromip() <= seek && ipa.getToip() >= seek) {
address = readAddress(mbb);
break;
} else if (ipa.getFromip() > seek && start != index) {
end = index;
} else if (ipa.getToip() < seek) {
start = index + 1;
if(start >= 25133) {
address = "不存在该ip地址";
break;
}
} else {
address = "不存在该ip地址";
break;
}
} catch (IOException ex) {
Logger.getLogger(FileDB.class.getName()).log(Level.SEVERE, null, ex);
}
}
return address;
}
这样利用随机生成的ip地址串进行测试,发现速度有了明细的提升,查询的次数可以达到2000+,其实这个时候自己还是挺高兴的,毕竟发现速度提升了很多,但是后来在网上发现,有人利用C语言写的查找IP地址的算法,每秒的查询次数可以达到10000+,当时心里一下就感觉到,跟他们的差距这么大,人家用一台计算机完成的工作,我至少要用5台。。
所以我只能在去寻找更好的办法,如果再想提升性能,现在已经使用二分法了,已经基本上是最快的搜索算法,肯定不能通过这个突破了,然后就想到了内存,将数据放到内存中,岂不可以极大的提高查询的速度。而且IP数据库的数据量也不是太大,最多10M+,那也占用不了多少内存,然后我就尝试着将这个ip的文本文件映射到内存中,使用的同样是二分法查找,这一次,在我用随机生成的ip地址测试时,竟然达到了10W+,哈哈,终于达到他们的水平,也说明java的性能也不必C差多少啊,完全可以满足我们的需求了,java好东西啊。。。当然他们那时候用的计算机性能可能没有我的性能好,但是这样的结果我已经比较满意了,起码可以和他们的相当了。
当然我的IP文件还有一些可以优化的地方,但是到这里可以先告一段落了,优化无止境。。。。。。
结束!