乐趣区

关于redis:redis-根据ip查询地址

需要

通常咱们的做法是把 ip 起始地址和完结地址转为 long 型寄存数据库,而后把须要查问的 ip 转 long 型,判断是否在某个 ip 区间内,如果在,则取出对应的地址信息,如果不在,则不存在 ip 地址信息。比方北京的 ip 范畴是 0 -100,上海的 ip 地址是 200-300,那所要查问的 ip 是 50,就属于北京,如果是 250,就是上海,如果是 150,那就是没有对应的地址。这边为了不便,数字是瞎编的。
如果用 sql 的话,是这样写的:

select * from table where 50>start and 50<end

下面 sql,start 是 ip 初始值,end 是完结值。
在 redis 中,能够通过有序汇合对分值进行排序以及依据分数进行排序。咱们能够这样设计,在有序汇合中,member 的值为 id+:+s|e,s 代表起始地位,e 代表完结。数据如下:

value score
1:s 0
1:e 100
2:s 200
3:e 300

查问的时候,能够获取小于查问值的第一个成员,比方 50,取到 1:s,因为是 s 结尾,所以阐明在某个区间内,再通过 1 获取详细信息。如果传入的是 150,则获取到 1:e,因为是 e 结尾,所以不在任何区间内。如果是 250,取到的是 2:s,因为是 s 结尾,所以阐明在某个区间内,再通过 2 获取详细信息。
下面失去的 1 或者 2 获取的详细信息,是通过 hash 存的,1 作为主键,内容寄存相应对象。

实际

@Test
public void init() {
    // 初始化有序汇合
    JedisUtils.zadd("ip:segment", 0, "1:s");
    JedisUtils.zadd("ip:segment", 100, "1:e");
    JedisUtils.zadd("ip:segment", 200, "2:s");
    JedisUtils.zadd("ip:segment", 300, "2:e");

    // 初始化 hash
    Map<String, String> map = new HashMap<>();
    map.put("name", "北京");
    JedisUtils.hmset("ip:info:1", map);


    Map<String, String> map2 = new HashMap<>();
    map2.put("name", "上海");
    JedisUtils.hmset("ip:info:2", map2);
}

@Test
public void test() {getInfo(-1);
    getInfo(50);
    getInfo(150);
    getInfo(250);
}

public void getInfo(double num) {Set<String> tuples = JedisUtils.zrevrangeByScore("ip:segment", num, Integer.MIN_VALUE, 0, 1);
    if (tuples.size() == 0) {System.out.println("暂无对应地址");
        return;
    }
    String member = tuples.iterator().next();
    if (member.endsWith(":e")) {System.out.println("暂无对应地址");
        return;
    }
    String id = member.replace(":s", "");
    Map<String, String> map = JedisUtils.hgetAll("ip:info:" + id);
    System.out.println(map);
}
退出移动版