使用redis存储全球IP库

将本文以行表形式存储于关系型数据库中的IP信息库,通过转换,存储到key-value型的Redis库中,以加快查询的速度。本文通过使用Redis的散列类型有序集合类型来实现这种需求。

在工程中常有这样的需求,即给定IP(本文一律考虑将点分十进制的ip转为无符号整型),从(全球)IP库中查找相关信息。若将IP库存储于关系型数据库中(本文仅截取部分字段用于阐明),其形式大概如下:

TAGIDFROMIPTOIPINFO1INFO2
TAG0117798307841779831039湖南省电信
TAG02987332096987332351江苏省镇江市电信
TAG0320268311042026831359江西省南昌市移动
TAG0420596610562059661311江苏省淮安市联通
TAG05832214272832214527江苏省南京市广电网

假设要查询给定IP的INFO1和INFO2信息,SQL语句如下:

SELECT INFO1,INFO2 WHERE IP >= FROMIP AND IP <= TOIP;

这样的语句查询关系型是数据库是比较耗时的。下面设法将上述数据存储到Redis中,主要借助Redis的散列类型和有序集合类型。

建表过程:
1. 将表中的每一个行以TAGID作为key,其余值作为value,以散列类型作为value的数据结构进行存储;
2. 将FROMIP和TAGID的映射关系(以FROMIP作为score),以有序集合的形式进行存储,这样所有的FROMIP将从小到大的顺序存储在Redis中;

查询过程(以java客户端jedis为例):
1. 将ip转换为无符号整型
2. 从redis有序集合类型中查找全球库中小于该ip的最大fromip,即确定该IP所在的起始区间;

jedis.zrevrangeByScore(key, max, min, offset, count);
key:有序集合类型的key值,目前为"fromipscore"
max:待查询的无符号整型IP
min:置为-1
offset:置为0,返回结果集的起始偏移量
count:置为1,只返回符合条件的第一条

如果查找不到,则直接返回,即该IP在库中查找不到;否则进行步骤3操作
3. 将步骤2返回的结果,作为新的key,查找redis散列类型的数据结构,并进行比较以确定该IP是否在上一步确定的区间内

Map<String, String>  val = jedis.hgetAll(key);
val中包含的示例如下:
{INFO2=联通, INFO1=江苏省南京市, TOIP=1910858495, FROMIP=1910858240}
从val中取出toip的值,转换为整型,并与待查找的ip进行比较;
如果待查询ip <= toip;则 val即为查询的结果集;否则查找不到

由于有序集合使用散列表和跳跃表实现,因此确定IP所在的起始区间时间复杂度不超过O(lgn);其次查找散列表的时间复杂度,在不发生冲突时是常数。下面在shell端,对上面过程进行演示,加深理解。

  • 将每行数据以散列表形式存储
127.0.0.1:6379> hmset TAG01 FROMIP 1779830784 TOIP 1779831039 INFO1 湖南省 INFO2 电信
OK
127.0.0.1:6379> hmset TAG02 FROMIP 987332096 TOIP 987332351 INFO1 江苏省镇江市 INFO2 电信
OK
127.0.0.1:6379> hmset TAG03 FROMIP 2026831104 TOIP 2026831359 INFO1 江西省南昌市 INFO2 移动
OK
127.0.0.1:6379> hmset TAG04 FROMIP 2059661056 TOIP 2059661311 INFO1 江苏省淮安市 INFO2 联通
OK
127.0.0.1:6379> hmset TAG05 FROMIP 832214272 TOIP 832214527 INFO1 江苏省南京市 INFO2 广电网
OK
  • 把FROMIP作为SCORE,将TAGID以有序集合进行存储,key为fromip:score
127.0.0.1:6379> zadd fromip:score 1779830784 TAG01
(integer) 1
127.0.0.1:6379> zadd fromip:score 987332096 TAG02
(integer) 1
127.0.0.1:6379> zadd fromip:score 2026831104 TAG03
(integer) 1
127.0.0.1:6379> zadd fromip:score 2059661056 TAG04
(integer) 1
127.0.0.1:6379> zadd fromip:score 832214272 TAG05
(integer) 1
  • 查询
IP为1779830785,该IP的tagid为TAG01
127.0.0.1:6379> zrevrangebyscore fromip:score 1779830785 -1 limit 0 1
1) "TAG01"
127.0.0.1:6379> hgetall TAG01
1) "FROMIP"
2) "1779830784"
3) "TOIP"
4) "1779831039"
5) "INFO1"
6) "\xe6\xb9\x96\xe5\x8d\x97\xe7\x9c\x81"
7) "INFO2"
8) "\xe7\x94\xb5\xe4\xbf\xa1"
127.0.0.1:6379> 
比较1779830785和结果集中的TOIP即可判断
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值