2012-04-03 11 views
8

Mam wiele zakresów IP różnych dostawców. Na przykładZakresy sklepów IP w Redis

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

przekonwertować ten IP do Int32:

P1: 3232235786 - 3232235826, 3232236048 - 3232236081, etc 

Moje zadanie: znaleźć nazwę dostawcy na podstawie adresu IP użytkownika (na przykład 192.168.2.20 (3232236052))

W MySQL jest to proste:

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

Jak zrobić to samo z Redis?

+0

Czy masz już swoje IP przechowywane w Redis? Jeśli tak, w jaki sposób je przechowujesz? –

+0

Przechowuję zakresy w MySQL DB, ale wiele zapytań do MySQL o nazwę dostawcy - to jest okropne :( – trong

Odpowiedz

14

To zależy, czy uważasz, że zakresy IP mogą się pokrywać czy nie. Jeśli nie, to rozwiązanie jest dość prosta:

  • wykorzystywać zbiór hash danych świadczących przechowują
  • użyć zset do indeksu maksymalną wartość swoich zakresach
  • odzyskać (unikalny) zakres którego max wartość ta jest większa niż IP
  • sprawdź, czy wartość min tym zakresie jest mniejszy niż oD

przykład:

Oto moi dostawcy. Każdy z nich jest identyfikowany za pomocą id. Należy pamiętać, że można dodać więcej właściwości dołączonych do każdego dostawcy:

> 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 

każdym razem, gdy dostawca jest dodawany do systemu, wskaźnik musi być zachowana (ręcznie: to Redis, nie jest relacyjna baza danych). Wynik to wartość maksymalna, członek to identyfikator zakresu.

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

Teraz kwerendy unikalny zakres odpowiadający adres IP, trzeba 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" 

Następnie program klient musi tylko sprawdzić, czy IP jest większa lub równa minimalnej adres zwróconego zakresu.

Teraz, jeśli uważasz, że zakresy mogą się nakładać, rozwiązanie jest o wiele bardziej złożone i zostało już wyjaśnione here.

9

Moim zdaniem najlepszym rozwiązaniem byłoby sorted set.

Aby wstawić zakres, użyj ZADD.
Do member należy przypisać nazwa zakresu. Aby uzyskać score, należy ustawić największą wartość w zakresie

ZADD ip_table 3232235826 some_name 

Następnie za znalezienie wykorzystanie zakresu ZRANGEBYSCORE z user_ip jak MIN_VALUE i limit = 1.

ZRANGEBYSCORE ip_table user_ip +inf LIMIT 0 1 

znajdzie ofertę o najmniejszej ip w punkcie końcowym, który jest większy niż lub równy user_ip.

+0

Jak uzyskać nazwę dostawcy w implementacji? – trong

+0

Członek powinien zawierać nazwę dostawcy. Poprawiłem to. –

0

Jeśli otrzymujesz te dane od dostawcy, takiego jak MaxMind, mogą istnieć już dostępne biblioteki, które wykonają to szybko i skutecznie. Nie sądzę, że w tym przypadku uzyskasz dużą wydajność za pomocą Redisa.

+0

Tak, zrobiłem jakiś test porównawczy i odkryłem, że używanie redis do wyszukiwania jest 10 razy wolniejsze – stupidbodo