Redis |存储IP和网络的最佳数据结构

时间:2020-08-25 07:38:24

标签: redis

我的目标是存储在Redis中:

  • 简单的IP地址,例如228.228.228.228
  • 228.228.228.0/24之类的IP网络

为了检查请求/响应周期是否 当前IP xxx.yyy.xxx.vvv位于(包含在)内部:

  • 普通ips

  • IP网络(例如228.228.228.228内部的228.228.228.0/24

ip和网络总数-少有1000个项目。

问题是–在Redis中存储纯IP和网络并进行上述检查而不从Redis获取数据的最佳方法(最佳结构)是什么?

谢谢。

P.S。当前IP已为人所知。

更新

好吧,让我们用示例简单一点。

我有2个ip和2个网络,我想检查其中是否包含某些ip。

# 2 plain ip
202.76.250.29
37.252.145.1

# 2 networks
16.223.132.0/24
9.76.202.0/24

有两种可能的方式可以包含确切的IP:

1)仅以纯ips为单位。例如,上面的结构中包含的202.76.250.29215.08.11.23并不是仅仅根据定义包含的。

2)Ip可能包含在网络内部。例如,9.76.202.100包含在网络9.76.202.0/24内,但不包含在普通ip列表内,因为没有确切的ip = 9.76.202.100.

有关ip网络的少量解释。非常简化。

ip网络代表ips范围。例如ipv4网络"192.4.2.0/24"代表256个ip地址:

IPv4Address('192.4.2.1'), IPv4Address('192.4.2.2'),
…
…
…
IPv4Address('192.4.2.253'), IPv4Address('192.4.2.254')

换句话说,ip网络是IP地址范围

from '192.4.2.1' up to '192.4.2.254'

在我们的示例中,9.76.202.100包含在网络9.76.202.0/24内部,作为范围内的地址之一。

我的想法是这样的:

任何IP地址都可以表示为整数。我们的IP地址之一 202.76.250.29转换为整数是3394042397

由于ip网络是一个ips范围,因此可以通过将整数范围内的第一个和最后一个ip转换为整数范围来将其转换为整数。 例如,我们的网络16.223.132.0/24代表IPv4Address('16.223.132.1')IPv4Address('16.223.132.254')之间的范围。或者整数283083777283083781到第1步的范围。

单个ip可以表示为整数与整数+ 1(包括下限,不包括上限)之间的范围。

很明显,可以通过将纯ip放入SET然后使用SISMEMBER来搜索纯ip。但是如何在网络内部进行搜索。我们可以对范围做些技巧吗?

2 个答案:

答案 0 :(得分:1)

“最佳”是主观的(在内存,速度等方面),但是您可以使用两个集合/哈希来存储它们。由于它们hashessets都是唯一的,所以都可以。如果您愿意,可以使用单个集/哈希值来保存IP地址和网络IP地址,但是我希望使用单独的设置,因为它们是两种不同类型的数据集(就像数据库表一样)。

然后您可以使用其中任何一个

  • SISMEMBER,时间复杂度为O(1)
  • HEXISTS,时间复杂度为O(1)。

可以在应用程序级别使用多个命令或lua脚本(在单个事务中)进行处理。

根据您的选择,将SADDHSET添加到密钥中(字段值为1)。

- 编辑:(希望我做对了)

对于网络地址的范围,请使用围绕两个点的整数(例如12.345.67.1-12.345.67.254)创建集合,范围将表示为12.345.67,并将其添加到集合中。当您要搜索12.345.67.x时,它将在您的应用程序级别中解析为12.345.67,并且您将使用SISMEMBER进行检查。使用HEXISTS进行哈希也可以做到这一点。

由于IP地址包含四个不同的数字和三个点,因此您将舍弃最后一个点和最后一个数字,其余将代表(我假设)网络范围。

答案 1 :(得分:1)

对于IP,您可以在O(1)时间内使用“设置”并按特定IP查询。

对于IP范围,我认为您可以使用带有Lua脚本的列表进行查询。列表的搜索时间为O(n),但是由于您只有1000个项目,因此O(N)和O(1)对于Redis在内存查询中不会有很大的区别。

相关问题