You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何高效存储与访问30亿条IP地理位置数据?

IP地址数据高效内存存储与访问方案咨询

我将30亿条IP地址存储在如下ip_location表中:

CREATE TABLE ip_location (
        id BIGINT AUTO_INCREMENT PRIMARY KEY,
        ip VARCHAR(15) NOT NULL,
        country VARCHAR(2),
        region_1 VARCHAR(255),
        region_2 VARCHAR(255),
        latitude DECIMAL(10, 6) NOT NULL,
        longitude DECIMAL(10, 6) NOT NULL,
        INDEX idx_ip (ip)
);

示例JSON数据:

{
        "ip": "1.2.3.4",
        "country": "US",
        "region_1": "California",
        "region_2": "San Francisco",
        "latitude": 37.769700,
        "longitude": -122.393300
}

我们的服务在全球范围受欢迎,希望对部分API做区域访问限制。每次调用API都查数据库验证位置会加重数据库和网络负载,打算把IP数据预加载到内存降负载。想请教这类数据的高效存储与访问方案,另外原本打算全量加载到Redis,但担心内存占用过高,这个顾虑是否正确?


解决方案建议

关于Redis内存占用的顾虑:完全正确

30亿条IP数据如果直接以字符串IP为键、完整位置信息为值存入Redis,内存占用会非常夸张。按每条数据的最小估算:IP字符串平均15字节,位置信息(国家2字节+地区约30字节+经纬度各8字节)大概48字节,再加上Redis键值对的元数据(至少几十字节),总内存保守估计会超过200GB,显然不现实,全量存Redis的方案不可行。

高效存储与访问方案推荐

1. IP段压缩存储:CIDR聚合+二分查找

IPv4本质是32位整数,绝大多数IP是连续段归属同一区域,没必要存储单个IP:

  • 先将数据库中的IP转换为整数形式并排序,把归属同一区域的连续IP聚合为CIDR段记录(包含起始IP整数、结束IP整数、区域信息)。30亿条单IP数据能压缩到几十万甚至十几万条段记录,内存占用骤降。
  • 用户请求时,将目标IP转为整数,用二分查找快速定位所属CIDR段,即可获取区域信息。这种方式内存占用仅几十MB级别,查询速度为O(logN),高效且低成本。

2. 内存数据库选型:用紧凑存储结构替代Redis字符串

如果一定要用内存数据库,避免使用Redis的普通字符串结构:

  • Redis Sorted Set:将IP整数作为score,序列化后的区域信息作为member。查询时通过ZRANGEBYSCORE找到第一个小于等于目标IP的记录,再验证是否在段内。聚合后的段数据量小,内存占用可控。
  • LevelDB/RocksDB(内存模式):这类嵌入式存储支持高效范围查询,将IP整数作为键、区域信息作为值,查询时做范围匹配,内存占用远低于Redis,适合大规模数据的内存存储。

3. 本地内存缓存+分层架构

  • 把聚合后的CIDR段数据直接加载到API服务进程的本地内存(比如用HashMap或自定义前缀树结构),完全避免网络开销,查询速度最快。
  • 针对高频访问的热点IP区域,可单独存入Redis做热点缓存,进一步加速查询,但核心依赖仍是本地内存的段数据。

4. 预计算IP整数优化

在数据库中新增ip_int BIGINT字段,提前将IP转换为32位整数存储并建立索引。后续的聚合、查询操作都基于整数进行,比字符串处理速度更快,还能减少存储和计算开销。

内容的提问来源于stack exchange,提问作者nguyendo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 02:13:29