-
- 如许? 按照IP获取归属地文字描述 -> 正则获取地区名 -> 按照地区名去数据库或缓存中获取地区ID
- 还是如许?将IP库数据导入数据库中(ip_start, ip_end, area_code) -> SQL查找
- 头部。位于文件的前8个字节。前4字节存放32位整数,值为数据项目组的开端在文件中的地位;后4字节也存放32位整数,值为数据项目组的停止在文件中的地位
- 主体数据项目组。由N个固定布局体构成,每个布局体12字节,为一条IP局限数据(ip_start, ip_end, area_code)。布局体的三个项目组也分别为32位有符号整数,各4字节。(area_code若是量小的话也可以应用1个字符)
建造一个本身的二进制IP库文件
添加时间:2013-6-11 点击量:一、媒介
有做过IP归属地查询功能的伴侣应当都有据说过纯真IP库,纯真IP库查询类似如许:
若你仅须要按照IP搜刮出用户的归属地文字然后显示出来,只要遵守该IP库的规矩进行二分查找并显示就OK了。(格局详解)
但若是你须要按照IP获取归属地文字描述,然掉队一步与本身已有的行政地区数据表接洽关系起来该如何处理惩罚呢?
粗看这两种应当是都可以实现,然则效力呢?都很差!希罕是面对并发稍高的应用,这两种体式格式都经不起考验。
为什么不按照纯真IP库(其他IP库也可以)的数据与本身的地区数据接洽关系起来,用本身的地区ID来庖代纯真IP库的地区描述,最后建造一个本身的二进制IP库文件呢?
让我们进入正题,看看如何按照纯真IP库数据建造一个本身的二进制IP库文件。
注:本文只申明大致思路,没有具体代码,感谢
二、筹办工作
我们须要筹办好两项目组的数据:
1. 纯真IP库解压后的txt文件。
纯真IP库后会有个ip.exe对象,应用上方的解压即可生成。
生成的数据如图1-1,我这个版本有可能444290条。
图1-1
2. 本身的国度省市级联数据表。
这个网上应当斗劲多,本身进行导入,表布局类似(area_id, area_level, area_name, area_pid),分别代表地区ID,地区等级,地区名称,父地区ID。
当然你也可以本身应用不合的布局,不影响我们此次的处理惩罚。
三、过程
数据已经有了,如今来规划下我们须要生成的IP库的机构。
从题目中就知道,我们须要生成的IP库是二进制的数据包,而不是通俗文本文件,那么我们的IP库文件布局应当是如何的呢?
如图所示:
可以看到,我们的布局是如许的:
IP数据包的布局已经定下来了,后面就是一步步处理惩罚了。
1. 逐条读取IP文本文件内容,IP转为32位有符号整数(自定义的ip2long),地区文字解析获取到终极地区
a. IP文本文件每行的规矩为:前15字节为IP肇端地址,后15字节为IP停止地址,最后为地区文字描述。
b. IP转为32位有符号整数只占4字节,且解决了PHP函数ip2long在32位与64位体系下值不合的题目,新的函数如下:
function ip2Long32(¥ip) {
¥ip = unpack(l, pack(l, ip2long(¥ip)));
return ¥ip[1];
} // end func当然,你也可以本身开辟PHP扩大,详见这边:http://www.cnblogs.com/iblaze/archive/2013/06/02/3112603.html
c. 地区须要获取到各级别地区名称(包含省、市、县、区等,这边国外只保存国度),正则如图:
2. 将获取到的地区信息转为地区ID
这项目组处理惩罚我不太好描述,因为可能每小我用到的地区都不一样,然则大致道理就是先按照最初级地区名称去查找ID(看实际景象,有可能要去掉市、县之类),若是没有则查找上一级,如此轮回,直到获取到地区ID。
若是没有查找到地区ID,则都归入未知。
3. 紧缩,紧缩后的文件约为5.08M
紧缩规矩如图,format中的值对应pack中的类型:
这边有个处所必须提示下,因为IP转为有符号32位整数,则128.0.0.0今后的IP都邑为负数,所以须要断定负数,并放入我们IP库的前面去,毕竟?成果是应用二分查找,须要为有序数据。
4. 查找IP,应用二分查找,44W条数据最多只须要搜刮19次,类似如下:
4. 单个测试,看起来速度还可以
5. 简单压测看结果
a. ab压测,应用本机的ab
b. 测试脚本在linux测试机(通俗PC机)
c. 压测脚本如下:
d. 压测语句: ab -n 10000 -c 50 http://192.168.206.71/ipdata.php?type=php
发挥解析还不错。呵呵
停止了,有什么更好的体式格式可以一路评论辩论下,感谢~