2012-04-03 10 views
8

私はさまざまなプロバイダーのIP範囲をたくさん持っています。例Redisにip範囲を格納

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: ... 

のために私は、このIPはINT32に変換:

P1: 3232235786 - 3232235826, 3232236048 - 3232236081, etc 

マイタスク:ユーザーのIPアドレス(例えば192.168.2.20(3232236052))により、プロバイダ名を見つけるため

MySQLでは簡単です:

select name from ip_ranges where l_ip <= user_ip and user_ip <= r_ip 

レディスと同じ?

+0

あなたのIPは既にRedisに保存されていますか?はいの場合、どのように保管していますか? –

+0

私はMySQL DBに範囲を格納しますが、プロバイダ名を取得するためにMySQLに多くのクエリを送っています - それはひどいです:( – trong

答えて

14

IP範囲が重複する可能性があるかどうかによって異なります。 ない場合は、解決策は非常に簡単です:

  • ストアプロバイダのデータにハッシュのコレクションを使用
  • がその最大(ユニーク)の範囲を検索インデックスにあなたの範囲の最大値をZSETを使用します

    :値はIP
  • チェックこの範囲の最小値はIP

例よりも低いよりも大きいです

私の提供元はこちらです。それぞれのIDはIDで識別されます。私は各プロバイダに取り付けられた複数のプロパティを追加することができ注意:

> 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 

プロバイダがシステムに追加されるたびに、インデックスが維持されなければならない(手動:これはRedisのではなく、リレーショナルデータベースです)。スコアは最大値、メンバーは範囲のIDです。

> 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" 

今すぐIPアドレスに対応するユニークな範囲を照会するために、あなたは2つの往復必要があります。

> 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" 

を次にクライアントプログラムは、ちょうどあなたのIPが最小アドレス以上であることを確認する必要があります返される範囲の

ここで、範囲が重複する可能性があると考えると、ソリューションははるかに複雑で、既に説明済みですhere

9

私の意見では、最高の解決策はsorted setです。

範囲を挿入するにはZADDを使用します。
memberを割り当てます。
にはscoreに範囲内の最高値を割り当てます。

ZADD ip_table 3232235826 some_name 

そしてMIN_VALUEと限界としてuser_ipはと範囲使用ZRANGEBYSCOREを求める= 1

ZRANGEBYSCORE ip_table user_ip +inf LIMIT 0 1 

それ以上user_ipはに等しいエンドポイントの最小IPと範囲を見つけます。

+0

実装のプロバイダの名前を取得する方法 – trong

+0

メンバーにはプロバイダの名前を入れるべきです。 –

0

MaxMindのようなサプライヤのデータを入手している場合は、これをすばやく効率的に利用できるライブラリが既に存在する可能性があります。この場合、Redisを使用して多くのパフォーマンスを得ることはできません。

+0

はい私はベンチマークを行い、ルックアップにredisを使用すると10倍遅くなることがわかりました – stupidbodo

0

これは、Didier Speziaが提案した と似ていますが、「ギャップ」が存在する可能性があるため、ソートセットで開始範囲と終了範囲を使用します。

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

関連する問題