背景
我正在构建一个IPAM应用程序,以跟踪和存储各个IPv4和IPv6地址的元数据。后端旨在成为无聊的,与供应商无关的关系数据库。
IPv6可能在广阔的可寻址空间中处理大量数据,但是所讨论的范围并不是天生就构成大数据的,因此我不愿意更改后端体系结构,而不会遇到我目前使用的方法更好的实际技术缺陷。通过时髦的NoSQL解决方案以关系和ACIDity为代价。
(我不是要记录整个地址空间,而只是要记录任意客户使用的实时地址。)
架构
标准化给定IP地址的字符串表示形式,并将其用作主键。 IPv4地址将转换为IPv6,并以ffff
为前缀。 IPv6地址被压缩并小写。
第二个字段指示该记录是哪个协议版本-4或6。这里的想法是,如果用户在IPv4子网中搜索记录,我可以快速排除IPv6空间,反之亦然。 / p>
接下来的八个字段(ugh)是地址(octet_1
,octet_2
等)中每个八位位组的整数表示。
索引
主键应该已经是它自己的唯一索引。
在(version, octet_1, ..., octet_8)
上创建一个附加索引。
查询
要搜索任一版本的特定IP,我可以像上面一样简单地对IP字符串进行规范化并搜索主键。
对于通过子网进行搜索,应用程序将计算范围的开始/结束地址,将两者都转换为IPv6,将它们都转换为八进制,并对所有记录之间的八进制发出查询。
此方法可能会遇到什么问题?有改进建议吗?
从ipv4s casted as ipv6 are not the same thing
到your index will explode / write performance will suck
的任何事物都是公平的游戏。
我构建了一个测试POC,用于验证该模式的功能,但是我担心该模型在生产环境中的任何潜在缺陷。
答案 0 :(得分:3)
如果您可以选择数据库后端,则选择PostgreSQL。它具有IP地址的内置类型,因此具有出色的性能和功能。
但是您说过您想成为数据库不可知的,所以让我们专注于此。在那种情况下,我只使用前缀为:: ffff:的IPv4地址进行字符串表示,然后仅使用小写的十六进制表示法并且不进行压缩。因此IPv4地址10.11.12.13将变为0000:0000:0000:0000:0000:0000:ffff:0a0b:0c0d。
几乎所有数据库在字符串上都具有良好的索引,并且使用这种表示法,您可以轻松地进行子网和范围查询。如果要所有IPv4地址,只需查询LIKE'0000:0000:0000:0000:0000:ffff:%'。因为它是从一开始就锚定的,所以标准btree索引应该可以正常工作。您可以使用<和>运算符对范围进行更复杂的查询,这又可以从标准索引中受益。这应该为您提供大多数子网查询。
在您的应用程序中,使用inet_pton等解析字符串以将其转换为所需的字符串应该不难。
在这种情况下,我会避免非正规化。通过以上所述,您不需要单独的版本或八位字节列。它们只会减慢速度,增加不一致的机会。
答案 1 :(得分:0)
在“架构”下,您没有给出实际的架构。
“ IPv4地址已转换为IPv6并以...开头”,这表明您不了解IPV6的意图和目的。
“ IPv6地址...小写。”背叛您不了解值与值表示之间的区别(“小写”可能会影响值的 表示 ,但会 从不 影响 值本身 )。
“如果用户在IPv4子网中搜索记录”,则表明您不了解OSI 7层模型的构思者在构思其网络通信模型时所考虑的关注点分离。 “搜索记录”与IP(v4 / v6)不在同一层。
“主键应该已经是它自己的唯一索引。”背叛您不了解关系数据管理。
您可能会觉得这不是您问题的答案,但实际上是。