Frage

Ich bin versucht, ein System zu entwickeln für ganzzahlige Packwerte von mehr als 65535 in eine ushort. Lassen Sie mich erklären.

Wir haben ein System, das Int32-Werten unter Verwendung einer Identity-Spalte von SQL Server generiert und werden durch eine in-Produktion Client-API beschränkt, die unsere Int32 IDs ushorts überläuft. Zum Glück nur der Client etwa 20 oder so Instanzen der Dinge mit dieser IDs - lasst sie Pakete nennen - zu einem bestimmten Zeitpunkt und es braucht nur bei den lokalen Geschwister sie einzigartig zu haben. Die allgemein akzeptierte Lösung ist unsere Int32 IDs ushorts übersetzt (und nein ich mein Casting nicht, ich meine Übersetzung), bevor sie an den Client zu übertragen, jedoch gibt es Stacheln mit diesem Ansatz:

  1. Einige IDs weniger als 65535 können jederzeit im Spiel auf einem bestimmten Client sein noch aufgrund nicht-Ablauf.
  2. Wir können keine ID Kollisionen haben - das heißt, wenn die Verpackung ID 1 an den Kunden geht, einen Algorithmus, der verfolgt, wie oft 65535 von einem Int32 entfernt wird, um eine ushort zu machen, wenn auf 65536 angewandt auch in 1 a führen würde, wodurch Kollision.
  3. Wir müssen in der Lage, den ushort in die Int32 bei der Rückkehr zu rekonstruieren.

Was wir zur Verfügung haben, dieses Problem zu lösen, ist ein einziges Byte mit Vorzeichen Feld, das wir hallt und gibt uns 127 Werte zu spielen (eigentlich 117, weil wir 0-9 für etwas anderes verwenden sind). Ich werde von hier aus bis dieser als „Byte-Feld“ beziehen.

Wir haben drei verschiedene Übersetzungsroutinen diskutiert:

  1. Multiplikativ: Laden im Byte-Feld, wie oft wir 65535 aus unserem Int32 entfernen, um eine ushort zu machen. Dies hat Kollisionsprobleme wie oben beschrieben.
  2. Serialized Session State: für jeden Kunden, generiert ein Sitzungs-ID auf Basis von Fakten über diesen Client. Dann speichern Sie eine 1: 1-Übersetzungstabelle von 1 bis zur Anzahl der Pakete beginnen geliefert so, wenn der Client zugreift unserem Server wieder das Inventar der Pakete zurück zu ihrer bekannten Datenbank-IDs übersetzt werden kann. Dies hat Overhead-Probleme, da wir in einer Datenbank serialisierten Sitzungszustand würde die Sicherung und wir wollen Hunderte bis Tausende von Transaktionen pro Sekunde unterstützen.
  3. abwechslungsreich algorithmischer Ansatz, wo das Byte-Feld eine ID eines Transformationsalgorithmus, der eine Int32 nimmt und verwandelt sie in eine ushort. Offensichtlich sind viele von ihnen gehen, einfach sein Multiplikativ (unsere Obergrenze von IDs erhöhen wir verändern können), aber einige müssen sein multiplikative mit einem kleineren boundry (wie 32768) mit einer Zahl hinzugefügt / abgezogen, um möglichst nahe an einem bekommen Zahl, die unter Geschwistern einzigartig garantiert werden. Dieser Ansatz prozessorintensiv ist, sondern sollten uns um Kollisionen vermeiden lassen, während skalierbare verbleibenden (wenn auch mit diesem Ansatz, den wir eine begrenzte Decke haben, die nicht erreicht werden, bevor das ushort Problem aufgrund Upgrades auf eigene weggeht).

Also meine Frage ist: Gibt es einen besseren Weg, als meine Ansätze oben, und wenn nicht, was soll ich für in Form von Algorithmen suchen (zum Ansatz # 3) eine Zahl zwischen 1 bis 65.535 zu erzeugen, wenn eine bestimmte Anzahl ist größer als 0 und muss einen Weg Hash nicht?

Zur Verdeutlichung: es ist nicht, dass die ushort Decke das größte Problem ist, sein, dass der Client-API eine ushort verwendet, so kann ich das Byte-Feld nicht auf dem Client kombinieren, um größere Werte zu erhalten (der Client-API ist nicht erweiterbar, aber schließlich Phase aus der Existenz).

War es hilfreich?

Lösung

In Bezug auf Ansatz 2:

Ihr zweiter Ansatz ist so ziemlich wie NAT funktioniert. Jeder TCP / UDP-Client auf dem lokalen Netzwerk zu 65.535 Ports in Betrieb nehmen (mit Ausnahme von Port 0) und einer privaten IP. Der Router kennt nur eine einzige öffentliche IP. Da zwei Clients beiden Quellport haben 300, kann es nicht einfach ersetzen nur die private IP mit einem öffentlich man, dass Kollisionen verursachen würde erscheinen. So ersetzt er die IP und "übersetzt" die Port (NAT: Network Address Übersetzung ). Auf dem Rückweg, übersetzen sie den Hafen zurück und ersetzt die Öffentlichkeit mit einer privaten IP wieder, bevor das Paket zurück weiterleiten. Sie würden nichts anderes, als das zu tun. Allerdings halten Router diese Informationen im Speicher - und sie sind nicht zu langsam, wenn (mit Hunderten von Computern sind NATed zum Internet manchmal und die Verlangsamung ist kaum spürbar in den meisten Fällen Unternehmen) NAT zu tun. Sie sagen, Sie zu tausend Transaktionen wollen eine zweite - aber wie viele Kunden wird es geben? Da dies vor allem die Größe des Speichers für die Sicherung der Zuordnungen benötigt definieren. Wenn es nicht zu viele Kunden sind, können Sie die Zuordnung mit einer sortierten Tabelle im Speicher halten, in diesem Fall Geschwindigkeit wird das kleinste Problem sein (Tabelle immer größer und Server über genügend Arbeitsspeicher ausgeführt wird, desto größer eins).

Was ist ein wenig unklar ist mir, dass Sie einmal sagen

  

Zum Glück nur der Client über   20 oder so Instanzen der Dinge mit   diese IDs - lasst sie Pakete nennen -   zu jeder Zeit gegeben, und es braucht nur zu   sie haben einzigartig unter den lokalen   Geschwister.

aber dann sagen Sie

  

Einige IDs weniger als 65535 kann immer noch sein,   im Spiel auf einem bestimmten Client jederzeit   aufgrund nicht-Ablauf.

Ich denke, was Sie wahrscheinlich von der zweiten Aussage gemeint ist, dass, wenn eine Client-ID anfordert 65536, ist es noch IDs unter 65535 haben könnte und diese können als so niedrig sein (sagen wir mal) 20. Es ist nicht, dass die Client-Prozesse IDs in gerader Ordnung, nicht wahr? So kann man nicht sagen, nur weil es jetzt 65536 angefordert wird, kann es einige kleinere Werte haben, aber sicher nicht im Bereich von 1 bis 1000, richtig? Es könnte in der Tat eine Referenz halten zu 20, 90, 2005 und 41238 und geht nach wie vor über 65.535, das ist, was Sie gemeint?

Ich persönlich wie Ihre zweite Ansatz mehr als die dritte, da es einfacher ist, eine Kollision in jedem Fall zu vermeiden und die Zahl zurück zu übersetzen ist eine einfache, einfache Bedienung. Obwohl ich bezweifle, dass Ihr dritter Ansatz auf lange Sicht funktionieren kann. Okay, Sie könnten ein Byte haben zu speichern, wie oft Sie subtrahiert 2 ^ 16 der Zahl. Sie können jedoch nur 117 * 2 ^ 16 als größte Zahlen subtrahieren. Was werden Sie tun, wenn Zahlen über das gehen? Die Verwendung eines anderen Algorithmus, der nicht subtrahieren ist, aber macht was? Teilen? Umschalt-Bits? In diesem Fall verlieren Sie Granularität, die diesen Algorithmus bedeutet nicht Hit jede mögliche Anzahl nicht mehr (es wird große Sprünge machen). Wenn es so einfach war nur eine magische Übersetzungsfunktion auf 32-Bit-Anwendung auf 16-Bit-macht von ihm (+ ein zusätzlichen Byte) und dann einfach zurück zu verwandeln, denkt jede Komprimierungsmethode in dieser Welt es benutzen würde, wie könnte es, nein Ganz gleich, was die 32-Bit-Zahl war, es immer zu 24 Bit (16 Bit + ein Byte) komprimiert nach unten. Das wäre Magie. Es ist nicht möglich, 32-Bit in 24 Bit zu packen und auch die gesamte Logik packen, wie es auch in sie zurück zu verwandeln. Sie werden einige externen Speicher benötigen, die uns auf Ihren zweiten Ansatz zurück bringt. Dies ist der einzige Ansatz, der funktioniert, und es wird für jede Zahl in 32-Bit-Nummernbereich arbeiten.

Andere Tipps

Ich kann von ein paar andere Optionen denken:

Gibt es weltweit weniger als 65.536 Einträge in der Datenbank? Wenn ja, dann könnte man eine Zuordnungstabelle halten, die nicht mit dem Sitzungszustand verknüpft sind, ist aber ein beibehaltenen Teil der Anwendung.

Sind die Mehrheit der Einträge bei Indizes kleiner als, sagen wir 50.000? Wenn das der Fall ist kann man solche Werte direkt abzubilden, und eine Karte mit der Sitzung für die übrigen im Zusammenhang verwendet werden.

Wenn solche Sitzungsdaten persistierenden ein Problem ist und die Zahl der Kunden relativ klein ist, könnten Sie Client / Sitzungsaffinität aktivieren und die Karte an den Server lokal halten.

Wenn es nicht eine Web-Anwendung ist, können Sie die Karte auf dem Client selbst halten.

Ich sehe jeden algorithmisch nicht, dass Kollisionen vermeiden würde - ich vermute, dass Sie immer mit einem Beispiel kommen könnten, die kollidieren würden

.

Wie viel „mehr“ als 65535 benötigen Sie? Sie können immer nur ein paar Bits von Ihrem „Byte-Feld“, wie die höherwertigen Bits der ID hinzuzufügen. Nur 2 Bits würden Sie 262.143 bekommen, 3 Bits würden Sie 524.287 erhalten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top