使用 Redis 检查 IP 是否在一个范围内
Checking if IP falls within a range with Redis
我有兴趣使用 Redis 检查 IP 地址(转换为整数)是否在 IP 范围内。范围很可能会重叠。
我找到了 this question/answer,虽然我无法完全理解其背后的逻辑。
感谢您的帮助!
在this discussion中,Dvir Volk 和@antirez 建议使用排序集,其中每个条目代表一个范围,并具有以下形式:
Member = "min-max" range
Score = max value
例如:
ZADD z 10 "0-10"
ZADD z 20 "10-20"
ZADD z 100 "50-100"
并且为了检查一个值是否在一个范围内,您可以使用 ZRANGEBYSCORE 并解析成员 returned.
例如,要检查值 5:
ZRANGEBYSCORE z 5 +inf LIMIT 0 1
这将 return 为“0-10”成员,您只需解析字符串并验证您的值是否介于两者之间。
检查值 25:
ZRANGEBYSCORE z 25 +inf LIMIT 0 1
将 return“50-100”,但该值不在该范围内。
编辑 - 因为我得到了反对票(评论解释为什么会很好),我从我的回答中删除了一些混乱。
@DidierSpezia 在您的链接问题中的回答是一个很好的答案,但如果您处于 adding/removing 范围,则很难维护。
However it is not trivial (and expensive) to build and maintain it.
我有一个更易于维护的答案,但计算多个范围可能会变得缓慢且内存昂贵,因为它需要克隆一组所有范围。
您需要将所有范围保存两次,分为两组。每个范围的分数将是它的边界值。
使用@DidierSpezia 示例中的集合:
A 2-8
B 4-6
C 2-9
D 7-10
你的两组将是:
ZADD ranges:low 2 "2-8" 4 "4-6" 2 "2-9" 7 "7-10"
ZADD ranges:high 8 "2-8" 6 "4-6" 9 "2-9" 10 "7-10"
查询一个值属于哪个范围,需要trim下边界高于查询值的范围,trim上边界低于查询值的范围。
我能想到的最有效的方法是克隆其中一组,trim根据上面给出的规则在其中一侧设置,改变范围的分数以反映另一个边界,然后 trim第二面.
查找 5 所属范围的方法如下:
ZUNIONSTORE tmp 1 ranges:low
ZREMRANGEBYSCORE tmp (5 +inf
ZINTERSTORE tmp 2 tmp ranges:high WEIGHTS 0 1
ZREMRANGEBYSCORE tmp -inf (5
ZRANGE tmp 0 -1
我有兴趣使用 Redis 检查 IP 地址(转换为整数)是否在 IP 范围内。范围很可能会重叠。
我找到了 this question/answer,虽然我无法完全理解其背后的逻辑。
感谢您的帮助!
在this discussion中,Dvir Volk 和@antirez 建议使用排序集,其中每个条目代表一个范围,并具有以下形式:
Member = "min-max" range
Score = max value
例如:
ZADD z 10 "0-10"
ZADD z 20 "10-20"
ZADD z 100 "50-100"
并且为了检查一个值是否在一个范围内,您可以使用 ZRANGEBYSCORE 并解析成员 returned.
例如,要检查值 5:
ZRANGEBYSCORE z 5 +inf LIMIT 0 1
这将 return 为“0-10”成员,您只需解析字符串并验证您的值是否介于两者之间。
检查值 25:
ZRANGEBYSCORE z 25 +inf LIMIT 0 1
将 return“50-100”,但该值不在该范围内。
编辑 - 因为我得到了反对票(评论解释为什么会很好),我从我的回答中删除了一些混乱。
@DidierSpezia 在您的链接问题中的回答是一个很好的答案,但如果您处于 adding/removing 范围,则很难维护。
However it is not trivial (and expensive) to build and maintain it.
我有一个更易于维护的答案,但计算多个范围可能会变得缓慢且内存昂贵,因为它需要克隆一组所有范围。
您需要将所有范围保存两次,分为两组。每个范围的分数将是它的边界值。
使用@DidierSpezia 示例中的集合:
A 2-8
B 4-6
C 2-9
D 7-10
你的两组将是:
ZADD ranges:low 2 "2-8" 4 "4-6" 2 "2-9" 7 "7-10"
ZADD ranges:high 8 "2-8" 6 "4-6" 9 "2-9" 10 "7-10"
查询一个值属于哪个范围,需要trim下边界高于查询值的范围,trim上边界低于查询值的范围。
我能想到的最有效的方法是克隆其中一组,trim根据上面给出的规则在其中一侧设置,改变范围的分数以反映另一个边界,然后 trim第二面.
查找 5 所属范围的方法如下:
ZUNIONSTORE tmp 1 ranges:low
ZREMRANGEBYSCORE tmp (5 +inf
ZINTERSTORE tmp 2 tmp ranges:high WEIGHTS 0 1
ZREMRANGEBYSCORE tmp -inf (5
ZRANGE tmp 0 -1