Java - ip2region - 基础篇(你知道ip2region吗?)
Java - ip2region - 基础篇(你知道ip2region吗?)
本篇主要介绍 ip2region, ip2region 支持很多客户端,本次主要以Java来介绍
在进行系统开发时,我们一般会涉及到获取到用户的具体位置信息,一般有两个方法:
- 根据GPS 定位的信息 (一般用于手机端)
- 用户的 IP 地址解析
每个手机都不一定会打开 GPS,而且有时并不太需要太精确的位置(到城市这个级别即可),所以根据 IP 地址入手来分析用户位置是个不错的选择。
下面就介绍一个分析 IP 地址一个比较好的东西 ip2region,这篇介绍一些基础的东西,下篇介绍使用与原理
前言
ip2region 是什么?
官方:ip2region - 准确率99.9%的离线IP地址定位库,0.0x毫秒级查询,ip2region.db数据库只有数MB,提供了java,php,c,python,nodejs,golang,c#等查询绑定和Binary,B树,内存三种查询算法
其实就是一个库,用于 IP地址解析定位用的,支持很多客户端,速度很快也不占内存,目前github已经到了10k star 了
特性:
- 准确率高,数据聚合多个供应商的数据
- 体积小,空间优化形成了仅仅几兆的 ip2region.db 文件
- 速度快,内置三种查询算法,支持毫秒级查询
- 支持多客户端,支持很多客户端,java、C#、php、c、python、nodejs、php扩展(php5和php7)、golang、rust、lua、lua_c, nginx
它的数据聚合了一些知名ip到地名查询提供商的数据,例如:(如果一下开放API或者数据都不给开放数据时ip2region将停止数据的更新服务)
- 淘宝IP地址库, http://ip.taobao.com/
- GeoIP, https://geoip.com/
- 纯真IP库, http://www.cz88.net/
ip地址相关知识
不知道的去百度百科了解一下 ip地址介绍
简短总结:
IPv4使用32位(4字节)地址,如果存储需要有 2^32 = 4294967296 约42.9 亿个地址空间来存储
关于位置信息,一般由 国家|区域|省份|城市|ISP
组成,如:
// ip地址|国家|区域|省份|城市|ISP
0.0.0.0|0|0|0|内网IP|内网IP
0.0.0.1|0|0|0|内网IP|内网IP
...
1.0.15.255|中国|0|广东省|广州市|电信
...
255.255.255.255|0|0|0|内网IP|内网IP
那我们需要根据ip地址获取位置信息,那如果想要直接根据ip地址获取到位置信息,即时间复杂度为O(1) 时,我们可以存储这些位置信息入文件中
假如使用 utf-8 进行存储,一条记录最短的情况是 0.0.0.0|0|0|0|0|0,有17位,占用17个字节,那么我们需要的地址空间为:
17 * 2^32 = 73014444032 B = 71303MB = 71GB 显然,不能够直接这样存储,谁会为了O(1)来存储72G的一个文件呀~
那么如何来又让速度快,又存储空间小呢?
空间文件优化
1、第一种 记录合成
因为 相邻 IP 具有相同的位置信息,所以可以其记录合成一条记录。如下文件数据(地址段依次递增):
//起始ip,结束ip,国家,区域,省份,市,运营商。无数据区域默认为0 根据开始ip地址升序排列0.0.0.0|0.255.255.255|0|0|0|内网IP|内网IP
...
1.0.8.0|1.0.15.255|中国|0|广东省|广州市|电信
...
224.0.0.0|255.255.255.255|0|0|0|内网IP|内网IP0.0.0.0|0.255.255.255|0|0|0|内网IP|内网IP
1.0.0.0|1.0.0.255|澳大利亚|0|0|0|0
1.0.1.0|1.0.3.255|中国|0|福建省|福州市|电信
1.0.4.0|1.0.7.255|澳大利亚|0|维多利亚|墨尔本|0
1.0.8.0|1.0.15.255|中国|0|广东省|广州市|电信
1.0.16.0|1.0.31.255|日本|0|0|0|0
1.0.32.0|1.0.63.255|中国|0|广东省|广州市|电信
在ip2region 库中的 ip.merge.txt 就是根据这样的规则来记录所有的IP地址,文件大小仅仅才 39.3 M ,如若根据ip地址查找位置信息,最简单的就是顺序遍历,当该ip在某条记录起始和结束ip之间时,即命中。
2、第一种 存储方式转变
上述的文件存储的ip地址都是以字符串的方式进行存储,比如像最短的字符串 0.0.0.0 占据 7 字节,最长的字符串 111.111.111.111 占据 15 字节
那如果将其转换成整型进行存储便可以大大节省空间,如果转换成整型,0.0.0.0 是 int(0), 111.111.111.111 是 int(1869573999),都仅仅占据 4 字节,可以省略大量的存储空间
3、第三种 位置信息优化
相同的位置信息会对应不同的 IP 段,所以仍有大量的位置信息在 IP 库文件中,我们可以在内存中只保留一份位置信息,并使用指针或者文件偏移量+数据长度来获取对应的位置信息
这个的意思就是也就是如:
|中国|华南|广东省|广州市|电信
其实这样的数据在文件中被重复存储了很多次,可以只存储一次,靠指针或者文件偏移量+数据长度来获取对应的位置信息
在ip2region 库中的 ip2region.db就是在 ip.merge.txt 基础上,为所有数据生成一份索引,并和数据地址组成一个索引项(index block),,然后按起始ip升序排列组成索引,并存储到数据文件的末尾,最终生成的 ip2region.db文件大小只有3.5M,根据索引获取位置信息,也直接将性能提升到0.0x毫秒级别
ip2region.db 结构介绍
ip2region.db 的文件结构图如下:
根据结构图,可以看到其主要分为以下四个部分:
- SUPER BLOCK:存储 INDEX 的起始位置(前四个字节) 与 INDEX 的结束位置(后四个字节),用于快速获取 INDEX 索引区域的地址
- HEADER INDEX: INDEX 区的二级索引 ,一个个 header index block 组成, 每个 header index block 对应存储 INDEX 中的 每个 index partion(4k) (前四个字节存储每个4K分区起始位置的index block 的起始ip值,后四个字节指向该index block的地址)
- DATA:数据部分 以 城市ip,国家,区域,省份,城市,运营商 形式存储, 例如:2163|中国|华南|广东省|深圳市|鹏博士
- INDEX:一个个 index partion 组成,对应 index block 的索引分区,每个index block 对应ip.merge.txt中每一条记录的 起始ip,结束ip , 位置数据(前四个字节存储起始ip,中间四个字节存储结束ip, 后四个字节存储数据信息 ,数据信息的 前三个字节保存数据地址(DATA中),后一个字节保存数据长度。)
查询算法
内置了三种查询算法,单次查询都在0.x毫秒级别:
- binary算法:基于二分查找,基于ip2region.db文件,不需要载入内存,单次查询在0.x毫秒级别
- b-tree算法:基于btree算法,基于ip2region.db文件,不需要载入内存,单词查询在0.x毫秒级别,比binary算法更快
- memory算法:整个数据库全部载入内存,单次查询都在0.1x毫秒内,C语言的客户端单次查询在0.00x毫秒级别。
本质:三种方法都是通过不同的方法先找到 index,然后根据二分查找找到 ip地址 处于的 index bolck(12个字节),根据后四个字节存储的数据信息找到数据,然后根据数据信息中的前三个字节找到对应的数据地址
binary搜索
基于二分查询方法,步骤如下:
- 把 ip值 通过 ip2long 方法转为长整型
- 通过 SUPER BLOCK 拿到 INDEX 的起始位置和结束位置
- 两个位置相减,然后 +1 得出index block 总数
- 采用二分法直接求解,比较 index block 和当前 ip 的大小,即可找到该ip属于的 index block(经典二分)
- 拿到该 index block 的后面四个字节(数据信息), 分别得到数据长度和数据地址
- 从数据地址读取拿到的所得长度的字节,即是搜索结果
b-tree 搜索
b-tree 搜索用到了 HEADER INDEX,第一步先在 HEADER INDEX 中搜索,再定位到 INDEX 中的某个 4k index分区搜索。
步骤:
- 把 ip值 通过 ip2long 转为长整型
- 使用二分法在 HEADER INDEX 中搜索,比较得到对应的 header index block
- header index block 指向 INDEX 中的一个 4K 分区,所以直接把搜索范围降低到 4K
- 采用二分法在获取到的 4K 分区搜索,得到对应的 index block
- 拿到该 index block 的后面四个字节(数据信息), 分别得到数据长度和数据地址
- 从数据地址读取拿到的所得长度的字节,即是搜索结果
memory算法
该方法和 binary搜索 方法类似,区别就是它将 ip2region.db 全部读进内存中再进行查找
相关链接
GitHub ip2region
Java - ip2region - 使用篇
Java - ip2region - 基础篇(你知道ip2region吗?)相关推荐
- java实现linkstring,【JAVA SE基础篇】32.String类入门
[JAVA SE基础篇]32.String类入门 1.字符串 1.String类又称作不可变字符序列 2.String位于java.lang包中,java程序默认导入java.lang包下所有的类 3 ...
- java 中间容器 表格_【JAVA SE基础篇】45.迭代器、Collections工具类以及使用容器存储表格...
本文将要为您介绍的是[JAVA SE基础篇]45.迭代器.Collections工具类以及使用容器存储表格,具体完成步骤: 1.迭代器 迭代器为我们提供了统一遍历容器(List/Map/Set)的方式 ...
- JAVA多线程基础篇-关键字synchronized
1.概述 syncronized是JAVA多线程开发中一个重要的知识点,涉及到多线程开发,多多少少都使用过.那么syncronized底层是如何实现的?为什么加了它就能实现资源串行访问?本文将基于上述 ...
- Java面试基础篇之集合
文章目录 你知道的集合都有哪些? 哪些集合是线程安全的? Collection 集合类和数组有什么不同? Collection和Collections有什么区别? 如何确保一个集合不能被修改? Lis ...
- java预科基础篇2021.2.3学习记录
java预科基础篇2021.2.3学习记录 初识博客 本以为老师会讲是在微博上写博客做记录,没想到会是很多程序员专用的博客 博客为音译,正确翻译结果为网络日记,英文为bog 较为专业的程序员用博客为: ...
- java se运算符优先级,【JAVA SE基础篇】10.运算符优先级与类型转换
[JAVA SE基础篇]10.运算符优先级与类型转换 1.运算符的优先级 运算符的优先级在考试中会考,了解即可,多用就会熟能生巧 实际使用过程中建议用小括号来分优先级 关键就是:逻辑非>逻辑与& ...
- JAVA红石_【Mc我的世界红石研究日记】第四期:红石基础元件(四)——JAVA版基础篇...
Hello,大家好,欢迎来到Mc元气工作室!本期给大家带来Mc我的世界红石研究日记·第四期!版本:JAVA1.14.3. 第三期答题互动答案 以下哪一个选项被红石比较器检测出的红石信号与其他三项不同? ...
- java se用哪个eclipse_【JAVA SE基础篇】5.eclipse的使用和运行
1.eclipse的版本介绍 所有版本的eclipse都按照系统分为32位和64位,如果你的JDK是32位,eclispe必须也是32位,eclipse应与JDK相符合 eclipse分SE和EE等版 ...
- 零基础入门 自学 JAVA SE 基础篇(九)instanceof final 开闭原则 多态 抽象(abstract)方法与抽象类 接口(interface)
JAVA SE自学 基础篇 多态 instanceof final 开闭原则 多态 抽象(abstract)方法与抽象类 接口(interface) 目标 父类型与子类型之间的转换及instanceo ...
最新文章
- 对象检测工具包mmdetection简介、安装及测试代码
- android UI进阶之布局的优化(二)
- Ext Js MVC系列二 利用Application和Viewport进行应用程序初始化和页面布局
- 【转载】Few-shot learning(少样本学习)和 Meta-learning(元学习)概述
- NodeJS学习笔记(一)——搭建开发框架Express,实现Web网站登录验证
- php与rest的关系,PHP与节点REST-API
- 关于ajax跨域的问题
- 简约大方干净明亮“现代简约细体字体”
- android iso系统下载 百度云,Windows 7 SP1官方原版ISO系统镜像所有版本下载集合
- 知网文献阅读器android,CAJViewer知网阅读器
- 架构师应该具备什么技能
- OA系统-部门和员工管理模块
- ESP8266 开发之旅 网络篇 无线更新 --OTA 固件更新
- 树莓派配置记录——aria2
- imatest测试分辨率使用教程
- YOLOV4垃圾检测召回率提升
- 在一家公司待久了没有目标,没有动力,我该怎么办?
- qt助手服务器超时,qt助手安装与使用教程
- 我是如何在知乎上赚钱的?真实经验分享,可操作性强
- Syzkaller学习笔记---更新syz-manager(二)
热门文章
- Redis学习篇3_事务及其监控(锁)、Jedis、SpringBoot整合Redis、RedisTemplate的json序列化、RedisUtil工具类
- 高薪程序员Java面试题精讲系列汇总
- MySQL 查询、子查询及连接查询
- 互联网公司春联大集合,太特么有才了
- java父原型,对象及原型丶Java教程网-IT开发者们的技术天堂
- JVM06-经典垃圾收集器
- Spring Cloud落地之Spring Cloud LoadBalancer 线上优化方案
- 有关彩票的python编程教程_python实现彩票系统
- GridView中BoundField与TemplateField的区别
- python月球地球质量计算_科学网—天文计算PyEphem指南 - 张金龙的博文