我的目标是在redis中存储:
普通ip地址,如 228.228.228.228
ip网络,如 228.228.228.0/24
以检查请求/响应周期是否为当前ip .yyy..vvv
在内部(包含于):
普通IP
或
ip网络(例如 228.228.228.228
内部 228.228.228.0/24
)
IP和网络的总数量-很少1000个项目。
问题是,在redis中存储普通ip和网络,并在不从redis获取数据的情况下进行上述检查的最佳方式(最佳结构)是什么?
谢谢。
p、 目前的ip已经知道了。
更新
好吧,让我们用例子来简化一下。
我有两个ip和两个网络,在那里我想检查是否包含某些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网络代表ip的范围。例如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网络是一个ip范围,因此可以通过将范围内的第一个ip和最后一个ip转换为整数来将其转换为整数范围。例如我们的一个网络 16.223.132.0/24
表示范围介于 IPv4Address('16.223.132.1')
以及 IPv4Address('16.223.132.254')
. 或整数范围从 283083777
高达 283083781
步进 1
.
单个ip可以表示为整数和整数+1之间的范围(包括下限,不包括上限)。
显然,在普通IP中搜索可以通过将它们放到 SET
然后使用 SISMEMBER
. 但是在网络内部搜索呢。我们能用射程做些小把戏吗?
2条答案
按热度按时间pieyvz9o1#
“最佳”是主观的(在内存、速度等方面),但您可以使用两个集合/散列来存储它们。因为它们都是独一无二的
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
. 用hash和HEXISTS
.由于ip地址包含四个不同的数字和三个点,您将丢弃最后一个点和最后一个数字,其余的将代表(我假设)网络范围。
d5vmydt92#
对于ip,您可以在o(1)时间内使用按特定ip设置和查询。
对于ip范围,我认为可以使用list和lua脚本进行查询。列表将有o(n)个搜索时间,但由于您只有1000个项目,所以对于redis内存查询,o(n)和o(1)不会有很大的区别。