一、实现方式

社区的“数据服务”会提供一个版本信息API用于查询最新数据版本的信息,一旦发现有新版本即可调用”外用下载API“去下载最新版本的xdb数据,核心步骤如下:

1. 调用“版本信息API”查询最新数据的版本信息。

2. 对比最新版本本地版本的信息,判断数据是否有更新。

3. 如果有更新则调用“外用下载API”去下载最新版本的xdb数据覆盖本地数据完成更新,如果没有更新则继续等待至少10分钟继续上述2个步骤。

二、版本检测

登录社区后,点击数据服务中的自动更新找到您的专属”版本信息 API“,API 格式类似如下:

// 该 API 地址不可用,仅作演示使用
https://ip2region.net/api/public/data/offline/ver_latest?t=cb0ecb9356.1.6844f7e6.OF001@JCB

备注:请至少间隔10分钟请求一次该API,请求过于频繁 token 参数会被系统屏蔽。

调用该API将返回您的数据服务的最新的版本信息(JSON格式),数据和注解如下:

{
    "errno": 0,         // 错误代码,0 表示成功,非 0 则表示失败
    "errstr": "OK",     // 错误描述,errno 为 0 时为 OK,否则为具体的错误描述
    "data": {
        "_source": "vinfo",
        "srv_id": "OF001@JCB",                   // 当前数据服务的 id
        "model": "v4_monthly",                   // 当前数据服务的型号,v4_monthly 表示月更
        "released_at": 1754110800,               // 最新数据的发布时间戳
        "released_dt": "2025-08-02 13:00:00",    // 最新数据的发布日期时间
        "expired_at": 1875586300,                // 当前数据更新服务的过期时间戳
        "expired_dt": "2029-06-08 12:11:40"      // 当前数据更新服务的过期日期时间
    }
}

上述返回参数中的data.released_at即为最新xdb数据的发布时间,要确定本地xdb数据是否有更新,我们还需要知道本地使用的xdb文件的发布时间。

C/PHP/Golang/Java等这些查询客户端提供了本地API用于获取指定xdb文件的生成时间戳,例如:

// C
xdb_header_t *header = xdb_load_header(handler);
header->created_at;   // xdb 文件的生成时间戳

// PHP
$header = XdbSearcher::loadHeaderFromFile($xdbFile);
$header['createdAt']; // xdb 文件的生成时间戳

// Golang
header := xdb.LoadHeaderFromFile(xdbFile);
header.CreatedAt      // xdb 文件的生成时间戳

// 其他语言可以查看对应的 Github / Gitee 对应的 binding 的源码

也有部分查询客户端没有提供这个API,查阅一下XDB-V4数据结构可以知道xdbheader段存储了文件生成的时间戳,通过一些简单的文件操作可以得到这个数据,具体代码逻辑如下:

// 以只读的方式打开对应的 xdb 文件
var handle = fopen("本地xdb文件的路径", "r");
// 文件指针移动到 4
fseek(handle, 4);
// 从当前位置读取 4 个字节 
var b4 = fread(handle, 4);
// 按照小端字节序解码得到一个无符号整数即为 xdb 文件的生成时间
var createdAt = b4[0] | (b4[1] << 8) | (b4[2] << 16) | (b4[3] << 24);

本地xdb文件的createdAt如果比版本信息 API返回的data.released_at要小即本地的 xdb 文件需要更新。

三、数据下载

登录社区后,点击数据服务中的自动更新找到您的专属”外用下载 API“,例如,V4-基础版满载版XDBAPI如下类似如下:

该 API 地址不可用,仅作演示使用
https://ip2region.net/api/public/data/offline/get_file?t=6e94fe429a.1.6842bce6.OF001@JCB&v=v001@full

备注:该链接每天限制最多 12 次访问。

直接使用下载工具或者浏览器访问该地址即可直接下载满载版XDB文件,例如:

// 使用 wget 下载最新版本的 xdb 文件并且存储到本地的 base_full.xdb 文件中
wget https://ip2region.net/api/public/data/offline/get_file?t=6e94fe429a.1.6842bce6.OF001@JCB&v=v001@full -O base_full.xdb

如果是在代码中使用http客户端去下载这个数据,一定要注意开启http重定向追踪,因为该 API 最终会重定向到一个阿里云的 oss 地址。例如,使用curl客户端的一些核心设置和描述如下:

var oss_url = "外用下载API地址";
var ch = curl_init();
curl_setopt(ch, CURLOPT_URL, oss_url);
curl_setopt(ch, CURLOPT_RETURNTRANSFER, 1);      // 返回 API 返回的数据, 不直接打印出来
curl_setopt(ch, CURLOPT_TIMEOUT, 1800);          // 设置超时时间,xdb 文件很大,下载过程可能比较长
curl_setopt(ch, CURLOPT_FOLLOWLOCATION, true);   // 跟踪 HTTP 的重定向,直接访问最终的 oss 地址

// 过滤掉 https 的一些验证
if (substr(oss_url, 0, 6) == "https:") {
    curl_setopt(ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt(ch, CURLOPT_SSL_VERIFYHOST, false);
}

使用中,无论您是直接将整个xdb文件缓存到内存中,还是直接基于文件去查询,xdb文件的下载过程建议按照如下方式来进行:

// 1,调用 “外用下载API” 将最新的 xdb 文件下载到一个临时文件,此处以 wget 作为演示。
wget https://ip2region.net/api/public/data/offline/get_file?t=6e94fe429a.1.6842bce6.OF001@JCB&v=v001@full -O base_full.tmp.xdb
// 2,将临时 xdb 文件 move 到正式线上文件,完成升级覆盖。
// move 这个操作不影响基于文件的查询使用。
// 如果您线上是使用的将整个 xdb 内存缓存的方式,需要重新载入新文件替换线上使用的 xdb 实例/引用。
move base_full.tmp.xdb base_full.xdb

四、升级脚本

依据上述描述的升级过程,您可以自己编写一个 bash 脚本使用 linux crontab 这样的定时任务来执行,也可以是一个升级程序,程序中定期休眠去检测,大致逻辑如下:

var ver_api_url = "";   // 版本信息 API 地址
var _dl_api_url = "";   // 外用下载 API 地址
var _created_at = get_local_xdb_created_at();   // 本地 xdb 文件的生成时间
for ( ; ; ) {
    // 1, 调用 “版本信息 API ” 获取最新数据的版本信息
    var latest = get_latest_release_info(ver_api_url);
    if (latest.data.released_at <= _created_at) {
        // 最新发布时间 <= 本地生成时间,不需要更新,继续等待下一次检测
        goto wait;
    }

    // 2, 调用 “外用下载 API ” 下载最新的 xdb 文件到一个临时文件
    var err = download_xdb_to_file(_dl_api_url, "base_full.tmp.xdb");
    if (err != null) {
        // 处理错误
        goto wait;
    }

    // 3, move 临时 xdb 文件到正式的 xdb 文件
    err = move("base_full.tmp.xdb", "base_full.xdb");
    if (err != null) {
        // 处理错误
        goto wait;
    }

    // 休眠等待 10 分钟
    wait:
    sleep(600);
}

社区将后续会提供一个自动升级程序的实现,并且开源到Ip2Region的代码仓库中,请关注社区的后续通知。