跳转至

IPv6 地址存储方案

一、IPv6 是什么

128 位地址,如 2001:0db8:85a3:0000:0000:8a2e:0370:7334

128 bit = 16 字节,int 装不下。

二、存储方案

方案 1:VARBINARY(16)

把 IPv6 转成 16 字节二进制存储。

public static byte[] ipv6ToBytes(String ipv6) {
    // 压缩形式展开
    // 按 : 分割,每段 16 bit
    // ...
}

MySQL:

address VARBINARY(16)

优点:空间小(16 字节)。 缺点:不可读,需要转换。

方案 2:VARCHAR(39)

直接存字符串。最长形式 8 组 4 位十六进制 + 7 个冒号 = 39 字符。

address VARCHAR(39)

优点:可读。 缺点:占空间大,不能范围查询。

方案 3:两个 BIGINT

128 bit = 两个 long(64 bit)。

ip_high BIGINT
ip_low  BIGINT

Java 用 InetAddress.getByName().getAddress() 拿 16 字节,分两段。

三、MySQL 函数

MySQL 5.6+ 支持:

SELECT INET6_ATON('2001:db8::1');   -- 转 VARBINARY
SELECT INET6_NTOA(...)             -- 转回字符串

四、选择

  • 生产环境:VARBINARY(16) + INET6_ATON
  • 简单场景:VARCHAR(39)

五、查询

按网段查询时,二进制存储才能做范围:

SELECT * FROM t
WHERE ip BETWEEN INET6_ATON('2001:db8::') AND INET6_ATON('2001:db8::ffff');

面试加分

  • IPv6 为什么是 128 位?地址空间大到几乎用不完。
  • 存储用二进制,不要用字符串,否则索引和范围查询都慢。