我的目标是存储在Redis中:
228.228.228.228
228.228.228.0/24
之类的IP网络为了检查请求/响应周期是否
当前IP xxx.yyy.xxx.vvv
位于(包含在)内部:
或
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.29
和215.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')
之间的范围。或者整数283083777
到283083781
到第1
步的范围。
单个ip可以表示为整数与整数+ 1(包括下限,不包括上限)之间的范围。
很明显,可以通过将纯ip放入SET
然后使用SISMEMBER
来搜索纯ip。但是如何在网络内部进行搜索。我们可以对范围做些技巧吗?
答案 0 :(得分:1)
“最佳”是主观的(在内存,速度等方面),但是您可以使用两个集合/哈希来存储它们。由于它们hashes
和sets
都是唯一的,所以都可以。如果您愿意,可以使用单个集/哈希值来保存IP地址和网络IP地址,但是我希望使用单独的设置,因为它们是两种不同类型的数据集(就像数据库表一样)。
然后您可以使用其中任何一个
SISMEMBER
,时间复杂度为O(1)HEXISTS
,时间复杂度为O(1)。可以在应用程序级别使用多个命令或lua脚本(在单个事务中)进行处理。
根据您的选择,将SADD
和HSET
添加到密钥中(字段值为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在内存查询中不会有很大的区别。