redis~有序聚集处置惩罚ip范围的查询问题

打印 上一主题 下一主题

主题 899|帖子 899|积分 2697

目前有两种方式对 IP 以及归属地信息举行缓存:

  • 第一种是将起始 IP,结束 IP 以及中间所有 IP 转换成整型,然后以字符串方式,用转换后的 IP 作为 key,归属地信息作为 value 存入 Redis;
  • 第二种是采用有序聚集和散列方式,首先将起始 IP 和结束 IP 添加到有序聚集 ip2cityid,城市 ID 作为成员,转换后的 IP 作为分值,然后再将城市 ID 和归属地信息添加到散列 cityid2city,城市 ID 作为 key,归属地信息作为 value。
第一种方式就不多做先容了,简单粗暴,非常不推荐。查询速度当然很快,毫秒级别,但缺点也十分明显,我用 1000 条数据做了测试,缓存时间长,大概 20 分钟,占用空间大,将近 1G。
下面先容第二种方式直接看代码

python语言实现
  1. # generate_to_redis.py
  2. # -*- coding:utf-8 -*-
  3. import time
  4. import json
  5. from redis import Redis
  6. def ip_to_num(x):
  7.     return sum([256 ** j * int(i) for j, i in enumerate(x.split('.')[::-1])])
  8. # 连接 Redis
  9. conn = Redis(host='127.0.0.1', port=6379, db=10)
  10. start_time = time.time()
  11. # 文件格式
  12. # 1.0.0.0|1.0.0.255|澳大利亚|0|0|0|0
  13. # 1.0.1.0|1.0.3.255|中国|0|福建省|福州市|电信
  14. with open('./ip.merge.txt', 'r') as f:
  15.     i = 1
  16.     for line in f.readlines():
  17.         item = line.strip().split('|')
  18.         # 将起始 IP 和结束 IP 添加到有序集合 ip2cityid
  19.         # 成员分别是城市 ID 和 ID + #, 分值是根据 IP 计算的整数值
  20.         conn.zadd('ip2cityid', str(i), ip_to_num(item[0]), str(i) + '#', ip_to_num(item[1]) + 1)
  21.         # 将城市信息添加到散列 cityid2city,key 是城市 ID,值是城市信息的 json 序列
  22.         conn.hset('cityid2city', str(i), json.dumps([item[2], item[3], item[4], item[5]]))
  23.         i += 1
  24. end_time = time.time()
  25. print 'start_time: ' + str(start_time) + ', end_time: ' + str(end_time) + ', cost time: ' + str(end_time - start_time)
复制代码
java语言实现

以下是通过 Java 来实现将 IP 起始值和结束值通过有序聚集存储,并根据传入的 IP 返回这个 IP 是否在 IP 范围聚集中存在的示例代码:

  • redis中存储的图

  • java代码如下
[code]package com.lind.redis;import com.lind.redis.config.LettuceRedisAutoConfigure;import lombok.extern.slf4j.Slf4j;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.test.context.junit4.SpringRunner;/** * 关于ip地址范围检索的测试 * * @author lind * @date 2024/3/6 11:14 * @since 1.0.0 */@Slf4j@RunWith(SpringRunner.class)@SpringBootTest(classes = { LettuceConnectionFactory.class, LettuceRedisAutoConfigure.class })public class IpRangeTest {    private static final String IP_RANGE_KEY = "ip_ranges";    @Autowired    RedisTemplate redisTemplate;    // 将 IP 地址转换为 long 范例的分数值    public static double convertIPToScore(String ip) {       String[] ipParts = ip.split("\\.");       if (ipParts.length != 4) {          throw new IllegalArgumentException("Invalid IP address format");       }       long score = 0;       for (int i = 0; i < 4; i++) {          long partValue = Long.parseLong(ipParts);          score = (score = start && ip

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

用户云卷云舒

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表