快速开始 · 结构化返回预览 (Data Structure Live Preview)#
三步完成接入:获取 .qzdb 二进制库 → 引入对应语言 SDK → 三行代码极速查询。SDK 原生适配动态自描述 Schema,直接返回零拷贝的结构化对象:
// 数据结构加载中...
SDK 快速接入 · 极简 3 行精髓 (Bento Code Box)#
采用 Stripe / Vercel Docs 风格的黑客风交互式代码面板,8 种语言统一规范,初始化与查询仅需 3 行核心代码:
// 1. 引入依赖: go get github.com/zengzhan/qqzeng-ip
// 2. mmap 零拷贝初始化 (全局单例) | 3. 极速查询 (微秒级)
searcher, _ := qzdb.Open("qqzeng_ip_ult_china.qzdb", 0, true)
info := searcher.Find("114.114.114.114")
fmt.Println(info.Get("country"), info.Get("province"), info.Get("city"), info.Get("isp"))
// 1. 堆外内存初始化 Reader (全线程安全共享)
QzdbReader reader = new QzdbReader.Builder(new File("qqzeng_ip_ult_china.qzdb")).build();
// 2. 结构化解析
GeoInfo loc = reader.find("114.114.114.114").orElse(null);
System.out.println(loc.getCountry() + " " + loc.getProvince() + " " + loc.getCity() + " " + loc.getIsp());
// 1. 只读 mmap 加载 (零堆分配 · Send + Sync)
let searcher = qzdb::from_file("qqzeng_ip_ult_china.qzdb").expect("load failed");
// 2. 结构化查询
if let Some(loc) = searcher.find("114.114.114.114") {
println!("{} {} {} ({})", loc.country(), loc.province(), loc.city(), loc.get("isp").unwrap_or("-"));
}
// 1. 打开数据库实例 (760万+ QPS 零 GC 分配)
using var reader = QzdbReader.Open("qqzeng_ip_ult_china.qzdb");
// 2. 结构化查询
GeoInfo loc = reader.Find("114.114.114.114");
Console.WriteLine($"{loc.Get("country")} {loc.Get("province")} {loc.Get("city")} ({loc.Get("isp")})");
from qzdb import QzdbReader
# 1. 创建解析器 (纯 Python 实现,零 C 扩展依赖)
searcher = QzdbReader("qqzeng_ip_ult_china.qzdb")
# 2. 查询解析
loc = searcher.find("114.114.114.114")
print(f"{loc.country} {loc.province} {loc.city} ({loc.isp})")
qzdb_reader_t searcher;
qzdb_init(&searcher, "qqzeng_ip_ult_china.qzdb"); // 1. 只读 mmap 映射
char buf[512];
qzdb_find_str(&searcher, "114.114.114.114", buf, sizeof(buf)); // 2. 微秒级查询
printf("结果: %s\n", buf);
const QzdbReader = require('./qzdb');
const reader = new QzdbReader.Builder("qqzeng_ip_ult_china.qzdb").build();
const loc = reader.find("114.114.114.114");
console.log(loc.get("country"), loc.get("province"), loc.get("city"), loc.get("isp"));
use Qqzeng\Ip\QzdbReader;
$reader = new QzdbReader("qqzeng_ip_ult_china.qzdb");
$loc = $reader->find("114.114.114.114");
echo $loc->get('country') . ' ' . $loc->get('province') . ' ' . $loc->get('city');
[+] 展开进阶用法 (原子指针平滑热更新 · 多实例 QzdbRegistry · 管道串流输出)
原子指针热替换 (Go / Java / C++)
通过 atomic.Pointer 在后台加载新版 .qzdb 校验无误后瞬间切换指针,实现 7×24 小时生产不停机零抖动更新。
管道串输出 (FindStr)
返回竖线分隔原始字符串:亚洲|CN|中国|江苏|南京|玄武|320102|电信|118.7969|32.0603|Asia/Shanghai,适合 Logstash / Flink 等流处理。
经典版 IP 数据库 DAT / DB 二进制解析 (历史兼容)#
除全新 QZDB 架构外,qqzeng 官方仍对早期 qqzeng-ip-3.0 ~ 6.0 .dat / .db 经典格式提供全语言解析兼容支持:
经典 DAT 文件结构 (Prefix Index + Binary Search)
基于前缀索引表 (256 槽位) + 记录索引区 (起止数值 + 偏移指针) + 文本内容池,二分检索复杂度 O(log N),内存常驻 10MB~20MB。
全新 QZDB vs 经典版 DAT 升级收益
• 双栈合一:QZDB 原生支持 IPv4/IPv6,经典 DAT 仅支持 IPv4;
• 性能提升:QZDB 跳转表+Trie 达 760万+ QPS(提升 300%);
• 动态 Schema:QZDB 支持 25 字段自描述拓展,经典版为固定字段。
统一 API 约定规范#
QzdbReader(path) / Open(path)初始化打开 .qzdb 文件,加载跳转表与只读字符串池,多协程/线程零并发锁开销。
find(ip) → GeoInfo返回结构化结果对象,提供字段 getter 访问与动态 Schema get(key) 适配。
findStr(ip) → "大洲|国家|省|市|..."返回以竖线分隔的管道串,与自动化测试管线 cross_verify.py 严格保持 1:1 对齐。
QzdbRegistry · 多实例与热更新支持多数据版本热隔离加载;通过原子指针切换实现生产不停机平滑热更新。
8 语言并发性能基准对比#
| 开发语言 | 内存映射模式 | 并发模型 | 性能特点 | 典型应用场景 |
|---|---|---|---|---|
| Rust | 只读 Mmap | 无锁 · Send / Sync | 零堆分配 · 零拷贝 · µs 级延迟 | 高性能代理 / 嵌入式 |
| C / C++ | 只读 Mmap | 无锁只读共享 | 极致体积 · 零内存开销 | Nginx 模块 / 网关 |
| Go | 只读 Mmap | Goroutine 安全 | 高并发无锁 · 极低 GC 压力 | 微服务 / API 网关 |
| C# | 只读内存加载 | 线程安全 | 760 万+ QPS · 零 GC 分配 | 企业级 .NET 8 服务 |
| Java | 堆外内存优化 | 线程安全 | 避免 JVM GC 停顿 | Spring Boot / 大数据 |
| Node.js | Buffer 加载 | 异步单线程 / Worker | BigInt 原生位运算优化 | 全栈 Web / Serverless |
| PHP | 常驻内存/文件 | 请求级隔离 | 零扩展依赖 · 极速部署 | Web 业务快速集成 |
| Python | 动态解析 | 多进程 / 协程 | 纯 Python 二进制解析 · 极简 | 离线清洗 / 分析脚本 |
手机号段归属地 SDK 集成(qqzeng-phone · 51.9万+ 全量覆盖)#
除了 IP 地址数据库,qqzeng 官方同步提供业界领先的中国手机号段归属地数据库与高性能 SDK(qqzeng-phone):全量覆盖 519,424+ 移动/联通/电信/广电/虚拟运营商号段,基于紧凑型二进制结构,单机查询性能突破 5,000万+ QPS,内存占用小于 10MB。
// 1. 加载 qqzeng-phone-3.0.dat (只读常驻内存 · 线程安全)
finder, err := qqzengphone.Load("qqzeng-phone-3.0.dat")
// 2. 微秒级查询 11 位手机号或 7 位号段
res, err := finder.Query("13800138000")
// 3. 结构化输出: 广东|深圳|518000|0755|440300|移动
fmt.Printf("%s %s 邮编:%s 区号:%s 行政码:%s 运营商:%s\n",
res.Province, res.City, res.ZipCode, res.AreaCode, res.GeoId, res.Isp)
// 1. 单例加载解析器 (5,000万+ QPS 无锁并发查询)
PhoneSearcher searcher = PhoneSearcher.load("qqzeng-phone-3.0.dat");
// 2. 查询手机号段
PhoneLocation loc = searcher.query("13800138000");
// 3. 结构化输出
System.out.println(loc.getProvince() + " " + loc.getCity() + " " + loc.getIsp() + " " + loc.getZipCode());
// 1. 零堆分配加载二进制文件 (Send + Sync 线程安全)
let searcher = PhoneSearcher::load("qqzeng-phone-3.0.dat")?;
// 2. 毫秒级号段查询
if let Some(loc) = searcher.query("13800138000") {
println!("{} {} 邮编:{} 运营商:{}", loc.province, loc.city, loc.zip_code, loc.isp);
}
// 1. 初始化解析器 (高吞吐零 GC 内存分配)
var searcher = PhoneSearcher.Load("qqzeng-phone-3.0.dat");
// 2. 极速查询
PhoneLocation loc = searcher.Query("13800138000");
// 3. 输出结果: 广东 深圳 (移动) 行政码:440300
Console.WriteLine($"{loc.Province} {loc.City} ({loc.Isp}) 行政码:{loc.GeoId}");
from qqzeng_phone import PhoneSearcher
# 1. 加载数据库文件 (纯 Python 原生字节流解析,零 C 依赖)
searcher = PhoneSearcher.load("qqzeng-phone-3.0.dat")
# 2. 查询归属地
loc = searcher.query("13800138000")
# 3. 输出: 广东 深圳 518000 0755 440300 移动
print(f"{loc.province} {loc.city} {loc.zip_code} {loc.area_code} {loc.isp}")
phone_searcher_t* searcher = qqzeng_phone_load("qqzeng-phone-3.0.dat"); // 1. 只读内存映射
phone_result_t res;
if (qqzeng_phone_query(searcher, "13800138000", &res) == 0) { // 2. 快速号段解析
printf("省份: %s, 城市: %s, 运营商: %s\n", res.province, res.city, res.isp);
}
qqzeng_phone_close(searcher);
const { PhoneSearcher } = require('qqzeng-phone');
// 1. Buffer 高速加载
const searcher = PhoneSearcher.load('qqzeng-phone-3.0.dat');
// 2. 结构化解析
const loc = searcher.query('13800138000');
console.log(loc.province, loc.city, loc.isp, loc.zipCode, loc.areaCode);
require_once 'qqzeng_phone.php';
// 1. 初始化解析器 (无扩展依赖)
$searcher = QqzengPhone::load('qqzeng-phone-3.0.dat');
// 2. 查询手机号段
$loc = $searcher->query('13800138000');
echo $loc['province'] . ' ' . $loc['city'] . ' ' . $loc['isp'];
qqzeng-phone 二进制 DAT 紧凑结构规范#
6 大输出字段与运营商覆盖矩阵#
| 字段名 | 数据类型 | 示例值 | 字段说明 |
|---|---|---|---|
| province | String | 广东 | 所属省份 / 直辖市 / 自治区 |
| city | String | 深圳 | 所属地级市 / 盟 / 州 |
| zip_code | String | 518000 | 所属地级市邮政编码 |
| area_code | String | 0755 | 长途电话区号 |
| geo_id | String / Int | 440300 | 国家统计局 6 位行政区划代码 |
| isp | String | 移动 | 基础运营商或虚拟运营商(移动/联通/电信/广电/虚商) |
动态 Schema 自描述与格式架构#
QZDB 是专为极速检索设计的二进制紧凑型 IP 数据库格式:支持内存映射、前缀跳转降维、全局字符串去重与动态 Schema 自描述。
二进制文件结构总览#
头部字段定义表(Header 64 字节)#
| 偏移 (Hex) | 长度 | 字段名 | 类型 | 说明 |
|---|---|---|---|---|
| 0x00 | 4B | magic | char[4] | 固定 ASCII "QZDB",用于文件格式校验 |
| 0x04 | 4B | version | uint32 | 文件格式版本号,当前最新为 3 |
| 0x08 | 2B | ip_flags | uint16 | 地址族标志位:bit0 = IPv4 支持,bit1 = IPv6 支持 |
| 0x0A | 2B | flags | uint16 | 扩展标志位(保留用于压缩/加密特性) |
| 0x0C | 4B | node_count | uint32 | Patricia Trie 节点总数 |
| 0x10 | 4B | record_count | uint32 | IP 网段叶子记录总数 |
| 0x14 | 4B | jump_entries | uint32 | 跳转表槽位总数(IPv4 固定 65536) |
| 0x18 | 4B | strpool_offset | uint32 | 字符串池在文件中的物理起始字节偏移 |
| 0x1C | 4B | strpool_size | uint32 | 字符串池总字节长度 |
| 0x20 | 4B | schema_offset | uint32 | 动态 Schema 结构元数据物理偏移 |
| 0x24 | 4B | schema_fields | uint32 | 当前版本字段总数量(如 pro 版 = 11) |
| 0x28 | 8B | build_time | uint64 | 构建时间戳(Unix Timestamp 毫秒) |
| 0x30 | 16B | checksum | uint8[16] | 128 位文件完整性校验哈希 |
动态 Schema 自描述机制#
schema_fields → ["continent","country_code",…]初始化时解析 Schema 段,构建字段名与叶子偏移数组的索引映射。
GeoInfo.get("city") / loc.city → string结构化对象支持按名称检索;对于未知或新增字段自动降级返回空值,完美兼容新老版本。
两阶段检索机制与复杂度#
转为 32/128 位整型
跳过 16 层递归
CPU 缓存命中极高
零锁 · 零堆分配
微秒级返回
五大商业版本选型 · 场景化精准匹配#
与官网选购体系(service)完全对齐:全系标配 IPv4/IPv6 双栈合一与 CIDR/Range 双格式,五大版本按需选型:
标准版
基础归属速查专业版
精细地理定位路由版
网络架构分析旗舰版
全能防风控至尊版
全球风控 · 金融级查看五大版本全要素 25 字段详细对比大表 (std / pro / asn / max / ult)
| 输出字段 / 核心属性 | 标准版 STD (6) | 专业版 PRO (11) | 路由版 ASN (8) | 旗舰版 MAX (15) | 至尊版 ULT (25) |
|---|---|---|---|---|---|
| cidr / start_ip ~ end_ip | ✓ | ✓ | ✓ | ✓ | ✓ |
| 大洲 (continent) / 国家代码 | ✓ | ✓ | ✓ | ✓ | ✓ |
| 省份 (province) / 城市 (city) | ✓ | ✓ | — | ✓ | ✓ |
| 区县 (district) / 行政区划 ID | — | ✓ | — | ✓ | ✓ |
| 经纬度 / IANA 时区 | — | ✓ | — | ✓ | ✓ |
| 运营商 (isp) | ✓ 基础 | ✓ 精细 | ✓ | ✓ | ✓ |
| ASN 自治域 / AS 名称 / 官方主域 | — | — | ✓ | ✓ | ✓ |
| 应用场景 (usage_type 30+ 细分) | — | — | ✓ | ✓ | ✓ |
| 中英双语扩展 (10项对照) | — | — | — | — | ✓ |
| 国际金融属性 (ISO3/货币/区号/国旗) | — | — | — | — | ✓ |
全国行政区划代码库集成(qqzeng-area · 三/四/五级全覆盖)#
官方同步民政部与国家统计局最新调整批复:提供省市区三级 (4,553 行)、街道乡镇四级 (44,980 行)、社区村五级 (665,552 行) 及 历史变更版 (8,338 行) 权威数据库,满足电商物流配送、用户实名认证、表单级联与大数据治理需求。
多级数据规格与全要素字段体系#
| 版本级别 | 记录总数 | 层级覆盖 | 包含核心字段 | 典型业务场景 |
|---|---|---|---|---|
| 三级旗舰版 | 4,553 行 | 省 / 市 / 区县 | 区划编码、父ID、全称、简称、拼音、经纬度、邮编、区号、ID路径 | 电商收货地址、全站注册选择、用户画像 |
| 四级乡镇版 | 44,980 行 | 省 / 市 / 区县 / 街道乡镇 | 区划代码、父ID、4级全称、省市区镇组合路径、拼音、经纬度 | 同城即时配送、网格化运营、物流末端调度 |
| 五级社区版 | 665,552 行 | 省 / 市 / 区 / 街道 / 社区村 | 12位统计用区划代码、城乡分类代码、5级完整组合路径 | 基层政务治理、人口普查、精准到村社区 |
| 历史变更版 | 8,338 行 | 1980年至今撤销合并对照 | 历史代码、历史名称、撤销年份、对应最新代码与最新省市区聚合 | 历史老旧数据清洗、旧档案归属地纠偏转换 |
前后端省市区多级联动与 JSON 结构适配#
嵌套树形结构 (Nested Tree JSON)
提供开箱即用的 [{code:"110000", name:"北京市", children:[...]}] 嵌套文件,直接绑定 Element Plus / Ant Design / Vant 等 UI 框架的级联选择器(Cascader)。
平铺索引结构 (Flat Key-Value Map)
提供以行政代码为 Key 的扁平 Map:areaMap["440305"] → {name:"南山区", parent:"440300", city:"深圳市", province:"广东省"},实现微秒级 O(1) 路径快速回溯。
树形递归查询 SQL 脚本示例 (WITH RECURSIVE)#
-- 1. PostgreSQL / MySQL 8.0+: 向上递归查找某个区县的完整省市区祖先链条
WITH RECURSIVE area_ancestors AS (
SELECT id, parent_id, name, level, CAST(name AS CHAR(200)) AS full_path
FROM qqzeng_area_tri WHERE id = 440305 -- 示例: 深圳市南山区
UNION ALL
SELECT a.id, a.parent_id, a.name, a.level, CONCAT(a.name, ' > ', r.full_path)
FROM qqzeng_area_tri a
INNER JOIN area_ancestors r ON a.id = r.parent_id
)
SELECT * FROM area_ancestors ORDER BY level ASC;
-- 2. 向下递归查询指定省份(如广东省 440000)名下的所有地级市与下属区县
WITH RECURSIVE area_descendants AS (
SELECT id, parent_id, name, level FROM qqzeng_area_tri WHERE id = 440000
UNION ALL
SELECT a.id, a.parent_id, a.name, a.level
FROM qqzeng_area_tri a
INNER JOIN area_descendants d ON a.parent_id = d.id
)
SELECT * FROM area_descendants;
SQL 导入一键提取器 (SQL Snippet Builder)#
交互式生成器:选择目标数据库 ➔ 选择数据版本 ➔ 选择网段模式,一秒渲染开箱即用的 DDL 与极速导入脚本:
-- 正在生成 SQL 脚本...
CSV / TXT 规格与编码规范#
| 配置项 | 标准规格 | 兼容说明 |
|---|---|---|
| 字符编码 | UTF-8 无 BOM | 亦提供 GBK / GB2312 编码纯文本版本定制 |
| 字段分隔符 | , (逗号) / \t (制表符) / | (竖线) | CSV 使用逗号,TXT 格式默认支持 Tab 或竖线分隔 |
| 换行符 | \n (LF) / \r\n (CRLF) | Linux / macOS 默认使用 \n,Windows 使用 \r\n |
| 表头 | 首行为英文标准字段名 | 导入数据库时指定 IGNORE 1 ROWS 或 FIRSTROW = 2 |
高并发工程实践与生产 FAQ#
生产部署建议#
单例复用 · 跨线程共享Reader 内部持有只读内存映射,进程启动时创建一次单例即可,多协程并发查询无需加锁。
mmap 预热 (Warm-up)服务冷启动后可预热遍历前 1000 个跳转槽位或使用 madvise(WILLNEED),消除首批请求缺页中断抖动。
零停机平滑热更新通过原子指针持有多版本 Reader 实例,后台加载新版完成校验后原子切换引用,老实例平滑回收。
容器内存限制规划常驻物理内存仅占用字符串池与跳转表大小;节点区按需调页,容器 Memory Limit 建议设为文件体积 × 1.25。
常见技术深度解答 (FAQ)#
1. QZDB 在每秒数十万高并发(High-Concurrency)微服务下,是否需要加锁或连接池?
QZDB 采用 只读 Mmap 内存映射 + 纯函数无状态检索 设计。SDK 在进程启动时完成前缀跳转表与全局字符串池的物理内存映射,后续所有并发查询(包括 Go 的 Goroutine、Java 的多线程并发、Rust 的
Send + Sync)均直接对只读内存执行最长前缀(LPM)比对与指针寻址,内部不存在任何共享可变状态,单进程实例可直接承载千万级 QPS 吞吐,无互斥锁竞争、无 GC 停顿。
2. 线上 7×24 小时不间断服务,每月 1 号更新 IP 库如何做到零停机(Zero-Downtime)平滑热更新?
1. 后台线程在内存中通过
QzdbReader.Open(new_path) 初始化加载新版数据库并校验校验和(Checksum);2. 校验成功后,通过原子指针(如 Go
atomic.Pointer / Java AtomicReference / C++ std::atomic)瞬间将全局引用指向新实例;3. 旧实例等待当前正在执行的微秒级查询自然结束后,由系统垃圾回收或引用计数安全释放,整个过程对外服务零抖动、零丢包。
3. 数据库后续月度发版扩充了新字段(如新增风险评分/国旗),老版本 SDK 会崩溃或报索引越界吗?
QZDB 二进制文件头部存储了元数据 Schema 定义。SDK 在加载时会动态解析本文件所包含的字段列表并建立字典映射。如果数据库新增了字段,老版 SDK 仍能正常读取已知字段;调用未知字段时安全返回空字符串或
None/null,绝不会发生内存越界或崩溃。
4. 为什么 QZDB 检索延迟能做到微秒级(µs),比 Redis 甚至传统 B 树快数十倍?
• 消除网络开销:Redis 即使走本地 Unix Domain Socket 也有上下文切换与协议序列化耗时(通常 0.5~2ms),而 QZDB 纯属进程内内存寻址。
• 两阶段算法:IPv4 高 16 位通过静态跳转表 O(1) 直达子树入口,跳过了前 16 次树分支比较;余下 16 位在极度紧凑的连续 Patricia 节点中匹配,平均仅需 6~8 次内存访问;
• 局部性优化:节点按前序遍历紧凑排布在连续字节流中,CPU L1/L2 缓存命中率高达 95% 以上。
5. 官方支持 8 种语言 SDK,如何确保跨语言在边界 IP 判定上的绝对一致?
每次构建发版时,自动化管线会抽取数百万条覆盖 IPv4/IPv6、边界网段、保留地址、重叠路由及极端 CIDR 的测试用例,同时驱动 Rust / Go / Java / C# / C / Node.js / PHP / Python 八种 SDK 独立执行解析,逐行比对管道串(Pipe String)输出。只有 8 语言哈希完全一致,数据库文件才会打包发布。
6. 五大版本(std / pro / asn / max / ult)企业应如何根据业务场景精准选型?
• 标准版 std (6字段):适合全局 CDN 调度、全站基础 UV 城市分布统计、省市级内容展示;
• 专业版 pro (11字段):电商配送、本地生活、区县级精细化运营、按经纬度计算附近服务;
• 路由版 asn (9字段):网络运维、BGP 路由穿透排查、跨国专线流量分流;
• 旗舰版 max (15字段):企业安全与风控首选。结合区县经纬度与 30+ 种使用场景(机房/云厂商/爬虫代理识别),有效防御刷单薅羊毛;
• 至尊版 ult (25字段):金融出海、跨境结算、多语言国际化站,自带中英双语、国家缩写、国际区号与货币代码。