store ip ranges in Redis

后端 未结 4 1890
失恋的感觉
失恋的感觉 2021-02-02 02:22

I have a lot of IP ranges of different providers. For example

P1: 192.168.1.10 - 192.168.1.50, 192.168.2.16 - 192.168.2.49,
P2: 17.36.15.34 - 17.36.15.255,
P3: .         


        
相关标签:
4条回答
  • 2021-02-02 02:56

    This is similar to what Didier Spezia proposed, but we use begin range and end range in sorted set, because there may be "gaps".

    https://github.com/nmmmnu/GeoIP-Redis

    0 讨论(0)
  • 2021-02-02 03:00

    If you're getting this data for a supplier like MaxMind, there may be libraries available already to do this quickly and efficiently. I don't think you'll gain much performance using Redis in this case.

    0 讨论(0)
  • It depends if you consider your IP ranges can overlap or not. If not, the solution is quite simple:

    • use a collection of hash to store providers data
    • use a zset to index the max value of your ranges
    • retrieve the (unique) range whose max value is greater than an IP
    • check the the min value of this range is lower than the IP

    Example:

    Here are my providers. Each of them are identified with an id. Please note I could add more properties attached to each provider:

    > hmset providers:1 name P1 min 3232235786 max 3232235826
    OK
    > hmset providers:2 name P3 min 1232235786 max 1232235826
    OK
    > hmset providers:3 name P3 min 2232235786 max 2232235826
    OK
    > hmset providers:4 name P4 min 4232235786 max 4232235826
    OK
    

    Each time a provider is added in the system, an index must be maintained (manually: this is Redis, not a relational database). Score is the max value, member is the id of the range.

    > zadd providers:index 3232235826 1 1232235826 2 2232235826 3 4232235826 4
    (integer) 4
    > zrange providers:index 0 -1
    1) "2"
    2) "3"
    3) "1"
    4) "4"
    

    Now to query the unique range corresponding to an IP address, you need 2 roundtrips:

    > zrangebyscore providers:index 3232235787 +inf LIMIT 0 1
    1) "1"
    > hgetall providers:1
    1) "name"
    2) "P1"
    3) "min"
    4) "3232235786"
    5) "max"
    6) "3232235826"
    

    Then the client program just has to check that your IP is greater or equal than the minimum address of the returned range.

    Now, if you consider the ranges can overlap, the solution is much more complex, and it has already been explained here.

    0 讨论(0)
  • 2021-02-02 03:14

    In my opinion best solution would be sorted set.

    To insert range use ZADD.
    To member assign range_name.
    To score assign highest value in range.

    ZADD ip_table 3232235826 some_name
    

    Then for finding range use ZRANGEBYSCORE with user_ip as min_value and limit = 1.

    ZRANGEBYSCORE ip_table user_ip +inf LIMIT 0 1
    

    It will find range with smallest ip at endpoint that is greater than or equal to user_ip.

    0 讨论(0)
提交回复
热议问题