2016-04-07 2 views
0

Wir haben eine Tabelle in unserer Datenbank, die statische IP-Reichweite von Städten und ihre IP-Adresse hat. Es sieht so etwas wie:Wie memcache oder speichere ich ein Schlüsselwertpaar, wenn der Schlüssel in Reichweite ist und nicht ein einzelner Wert?


IP-TO, IP-FROM, CITY

100, 110, A

111, 168, B

...

965, 1000, Z

Ich habe Beispieldaten erwähnt. Die realen Daten sind riesig mit fast 64.000 Zeilen in der Tabelle.

Für jeden Benutzer auf unserer Website stellen wir fest, ihre Stadt von ihrer IP-Adresse, die von SQL-Abfrage auf SQL Express Server ausgeführt wird.

Da die Daten statisch ist, beispielsweise jeder Benutzer mit IP in Bereich von 100 bis 110 Stadt A gehört, sind wir unnötig Datenbank schlagen jedes Mal.

Wir dachten daran, jeden einzigartigen IP-Besuch zu cachen. Zum Beispiel: IP-100 IP-101 bis A ... IP-110 bis A

abgebildet abgebildet auf einem zugeordnetes Dies würde aber 64k Schlüssel in memcache schaffen und ich fühle mich dort kein Punkt der Speicherung mehrerer ist Schlüssel, die denselben Wert haben, wenn wir den Bereich kennen.

Können wir das irgendwie in einer besseren Art und Weise das heißt von mindestens mem Cache-Schlüssel oder einen anderen Ansatz zusammen mit?

+0

Im Beispiel, das ich sehe, gibt es eine Differenz von 10 in jeder IP-Bereich. Hat der Bereich immer einen konstanten Wert? –

+0

Nein. Dies sind nur Beispieldaten. So ist es nicht. Ich würde das für bessere Klarheit ändern. – maverick

Antwort

0

Eine Liste von IP-Adressen kann sortiert werden (da es sich im Wesentlichen um Zahlen handelt). Wenn Sie eine große nicht überlappende Liste von IP-Bereichen haben, können Sie sie in eine große Liste sortieren. Wenn Sie eine große, sortierte Liste von Werten haben, können Sie eine binary search darauf tun. Mit 64.000 Elementen können Sie die ganze Liste in ungefähr 16 Vergleichen durchsuchen (praktisch sofort).

Mit der richtigen Indizes und Abfragen, könnte Ihre DB Lage sein, dies zu tun für Sie. Wenn Sie der Meinung sind, dass es auf andere Weise schneller gehen könnte (Tipp: Verwenden Sie Profiling, um festzustellen, ob es wirklich ist!) Oder sind Sie besorgt über die zusätzlichen Reisen in die Datenbank, können Sie die gesamten Daten der Tabelle im Speicher zwischenspeichern und die Liste durchsuchen. Auf Hochrangiger Ebene:

public class IPRangeCache 
{ 
    private List<IPRangeRecord> sortedRangeRecords = null; // get from database 

    public string GetCity(IPAddress ip) { 
     // binary search to find from sortedRangeRecords 
    } 
} 

Die binäre Suche muss sowohl die Anfangs- als auch die Endnummer berücksichtigen. Ein benutzerdefinierter Vergleicher oder eine benutzerdefinierte binäre Suche sollte dies möglich machen. Dies sollte sehr schnell sein.

könnten Sie auch versuchen, die letzten paar Minuten des Caching im Wert von IP-Adressen in einem Wörterbuch, aber ich denke, dass es unwahrscheinlich ist, schneller sein.

0

Wir können C# generisches Wörterbuch verwenden.

Wir erstellen eine Klasse, die den IP-Bereich enthält. Diese Klasse fungiert als Schlüssel für das Wörterbuch.

class IP_Range 
{ 
    public int MinIP { get; set; } 
    public int MaxIP { get; set; } 
} 

Wir werden dann eine comparer Klasse erstellen müssen, die beim Vergleich der Schlüssel des Wörterbuchs helfen.

class IP_RangeComparer : IEqualityComparer<IP_Range> 
{ 
    public bool Equals(IP_Range r1, IP_Range r2) 
    { 
     return (r1.MinIP == r2.MinIP && r1.MaxIP == r2.MaxIP); 
    } 

    public int GetHashCode(IP_Range r) 
    { 
     return r.MinIP.GetHashCode(); 
    } 
} 

Wir können dann ein allgemeines Wörterbuch erstellen und verwenden, wie unten:

IDictionary<IP_Range, string> myCache = new Dictionary<IP_Range, string>(new IP_RangeComparer()); 

// Adding entries 
myCache.Add(new IP_Range() { MinIP = 100, MaxIP = 110 }, "A"); 
myCache.Add(new IP_Range() { MinIP = 111, MaxIP = 168 }, "B"); 
myCache.Add(new IP_Range() { MinIP = 169, MaxIP = 200 }, "C"); 

// Reading the dictionary 
string city = myCache[new IP_Range() { MinIP = 169, MaxIP = 200 }]; 

Siehe this article für weitere Erläuterungen.

Hinweis: Um den Schlüssel für die bestimmte IP zu finden, nach der Sie suchen, müssen Sie über die myCache.Keys-Auflistung iterieren.

0

Sie können eine Instanz der IpAddress Klasse from the value erstellen und dann nur one of the bytes als Cacheschlüssel verwenden. Auf diese Weise wirst du nur einmal in die Datenbank für 001.xxx.xxx.xxx, einmal für 002.xxx.xxx.xxx usw.

var address = new IPAddress(value); 
var bytes = address.GetAddressBytes(); //an array of four bytes 
Verwandte Themen