我有一个用例,我不知道如何解决。我在这里要求它为我需要学习解决这个问题提供一些指导。
1.1.1.2
或CIDR
范围,例如1.1.1.1/24
要求如下
- Save all the IP address which comes as above format in-memory
- Search should work as following
- if I have IP address as 1.1.1.2 and 1.1.1.1/24, it should match the specific IP address 1.1.1.2 and not the CIDR range it falls into (1.1.1.1/24)
- If specific IP address is not found but CIDR range is available, CIDR range is returned
- if no match is found, return null/throw exception
问题
- 什么数据结构可以帮助我解决这个问题?尝试?
- 你会采取什么方法?
- 如何确保它不会消耗太多内存并且搜索速度很快(将会有一些合理的权衡)
谢谢
答案 0 :(得分:4)
我会使用二叉树(这种树称为Radix Trees):
搜索:只需使用您拥有的地址导航树。如果你最终得到一片叶子,那么你就拥有了那个特定的IP地址,否则就是#34;最低的"带标志的节点(参见第3点)是您拥有的最具体的CIDR范围。
示例:让我们使用8位IP和2位"部分"地址;在插入1.1.1.0/6之后,树将是(IP之后的数字是"包含"标志,nils是假叶子)
<root> -- nil
|
00.00.00.00/1 (0) -- nil
|
01.00.00.00/2 (0) -- nil
|
01.00.00.00/3 (0) -- nil
|
01.01.00.00/4 (0) -- nil
|
01.01.00.00/5 (0) -- nil
|
01.01.01.00/6 (1) --nil
|
nil
如果您查找IP地址1.1.1.1,您将在1.1.1.1/6处停止,这是一个CIDR范围,因为它具有零个孩子并且是最具体的(在树中)。如果您现在插入1.1.1.1,那么树将是
<root> -- nil
|
00.00.00.00/1 (0) -- nil
|
01.00.00.00/2 (0) -- nil
|
01.00.00.00/3 (0) -- nil
|
01.01.00.00/4 (0) -- nil
|
01.01.00.00/5 (0) -- nil
|
01.01.01.00/6 (1) -- nil
|
01.01.01.00/7 (0) -- nil
|
01.01.01.01 (1)
1.1.1.1没有叶子,因为它是IP地址。最后,让我们插入1.1.2.1
<root> -- nil
|
00.00.00.00/1 (0) -- nil
|
01.00.00.00/2 (0) -- nil
|
01.00.00.00/3 (0) -- nil
|
01.01.00.00/4 (0) --------------------+
| |
01.01.00.00/5 (0) -- nil 01.01.10.00/5 (0) -- nil
| |
01.01.01.00/6 (1) -- nil 01.01.10.00/6 (0) -- nil
| |
01.01.01.00/7 (0) -- nil 01.01.10.00/7 (0) -- nil
| |
01.01.01.01 (1) 01.01.10.01 (1)
答案 1 :(得分:2)
首先,您需要确定一些决策点。这必须是完全确定的。您说的唯一决定点是首先检查主机地址(/ 32),然后寻找更短的掩码。
1.1.1.1/24
,其中
地址长度超过掩码长度?你有没有假设
它是一个仅限主机的地址(1.1.1.1/32
),还是您在寻找上述决策点发挥作用的子网(1.1.1.0/24
)?您将需要以合理的速度克服几百万个地址所需的内存消耗问题。
我将假设主机地址将是您拥有的最大地址数,并且随着掩码长度变短,每个掩码长度的地址将逐渐减少。
如果使用散列表(32个掩码长度各占一个),则可以从最长的掩码长度(/ 32)表开始,如果找不到匹配,则查看短掩码长度表,具体取决于关于上述确定性规则。
例如,如果您的问题中包含1.1.1.1/24
,则假设您的汇总数为1.1.1.0/24
,1.1.0.0/23
和1.1.0.0/22
。
Table /32
1.1.1.1
Table /31
not found
Table /30
not found
Table /29
not found
Table /28
not found
Table /27
not found
Table /26
not found
Table /25
not found
Table /24
1.1.1.0
Table /23
1.1.0.0
Table /22
1.1.0.0
Table /21
not found
Table /20
not found
Table /19
not found
Table /18
not found
Table /17
not found
Table /16
not found
Table /15
not found
Table /14
not found
Table /13
not found
Table /12
not found
Table /11
not found
Table /10
not found
Table /9
not found
Table /8
not found
Table /7
not found
Table /6
not found
Table /5
not found
Table /4
not found
Table /3
not found
Table /2
not found
Table /1
not found
例如,使用1.1.1.1/24
:您可以开始在/32
表中查找主机地址。如果您没有找到,那么AND
带有掩码的地址将在1.1.1.0
表中获得/24
。如果你没有找到,AND
使用下一个较短的掩码并查看该表。重复,直到找到匹配或掩码长度达到0
。具体如何执行此操作取决于您上述决策所产生的算法。
对于每个主机地址或聚合,这只占用一个32位内存块,但是,只有几亿个地址,它不会少量。性能将高度依赖于所使用的散列算法,但它应该表现得非常好。
答案 2 :(得分:0)
postgreSQL支持inet,cidr地址以及内置函数来搜索它们(以及范围类型)。
http://www.postgresql.org/docs/9.4/interactive/datatype-net-types.html
不确定这是不是你要问的。