Frage

Ich möchte eine kurze, eindeutige ID erzeugen, ohne auf Kollisionen geprüft hat.

ich zur Zeit so etwas wie diese, aber die ID ich generiere derzeit wird zufällig ausgewählt und in einer Schleife für Kollisionen Überprüfung ist ärgerlich und teuer, wenn die Anzahl der Datensätze deutlich wächst.

Normalerweise über Kollisionen sich Gedanken ist kein Problem, aber die eindeutige ID I generieren wollen, ist eine kurze eindeutige Zeichenfolge 5-8 Zeichen, alphanumerisch, wie tinyurl der Fall ist.

EDIT:. Ich möchte mit 5 Zeichen beginnen, und wenn ich 60 Millionen Einträge schlagen, dann bis 6 gehen .. so weiter und so fort

Zu diesem Zweck Ich dachte, ich könnte einen auto_increment Wert verwenden, die von den Benutzern verborgen ist, und präsentieren sie stattdessen mit einem MD5 oder einem anderen Verfahren eine eindeutige Zeichenfolge aus, dass zu erzeugen.

erzeugten Strings sollte nicht angezeigt werden linear, so einfach die auto_incremented ID in base 36 Umwandlung [0-9A-Z] ist ein bisschen zu simpel, aber eine Funktion so etwas wie das ist, wo ich mit diesem gehe.

EDIT: Sicherheit ist kein Problem, da dies zu sichern Informationen nicht verwendet werden. Es ist einfach eine Verknüpfung zu einer längeren Zeichenfolge. Danke.

Vielen Dank für Ihre Anregungen und entschuldigen uns für die Verzögerung. Zahnarzt ..

War es hilfreich?

Lösung

Sie brauchen etwas, das durch die Konstruktion richtig ist, das heißt eine Permutation Funktion: Dies ist eine Funktion, die eine Eins-zu-eins, reversible Zuordnung einer ganzen Zahl (Ihre sequentiellen Zähler) zu einem anderen der Fall ist. Einige Beispiele (eine beliebige Kombination dieser sollte auch funktionieren):

  • einige der Bits invertierende (F.I. eine XOR Verwendung in ^ PHP)
  • die Orte von Bits Swapping (($ i & 0xc) >> 2 | ($ i & 0x3) << 2), oder einfach nur die Reihenfolge aller Bits Umkehr
  • Hinzufügen eines konstanten Wert Modulo Ihre maximale Reichweite (muss um einen Faktor zwei, wenn man dies mit den oben ist kombiniert)

Beispiel: Diese Funktion konvertiert 0, 1, 2, 3, 5, .. in 13, 4, 12, 7, 15, .. für Zahlen von bis zu 15:

$i=($input+97) & 0xf;
$result=((($i&0x1) << 3) + (($i&0xe) >> 1)) ^ 0x5;

Bearbeiten

Eine einfachere Möglichkeit wäre einen Kongruenzgenerator (LCG, die in der Regel zur Erzeugung von Zufallszahlen verwendet wird) zu verwenden, die durch eine Formel der Form definiert ist:

X_n+1 = (a * X_n + c) mod m

Für gute Werte von a, c und m, die Folge von X_0, X_1. . x_m-1 werden alle Zahlen zwischen 0 und m-1 genau einmal enthalten. Jetzt können Sie von einem linear ansteigenden Index starten, und verwenden Sie den weiter Wert in der LCG-Sequenz als „geheim“ drücken.

EDIT2

Umsetzung: Sie können entwerfen Sie Ihre eigenen LCG Parameter , aber wenn Sie es falsch wird es nicht decken die vollständige Palette (und haben Duplikate so), so werde ich eine veröffentlichte verwenden und versucht, von hier eingestellten Parameter von dieses Papier :

a = 16807, c = 0, m = 2147483647

Dies gibt Ihnen einen Bereich von 2 ** 31. Mit pack () Sie die resultierende ganze Zahl als String zu bekommen, base64_encode () macht es eine lesbare Zeichenkette (bis zu 6 signifikante Zeichen, 6 Bits pro Byte), so könnte dies Ihre Funktion sein:

substr(base64_encode(pack("l", (16807 * $index) % 2147483647)), 0, 6)

Andere Tipps

Sie könnten wahrscheinlich einen MD5-Hash der aktuellen Datetime / Zufallszahl generieren und gestutzt es Sie in die Länge benötigen (5-8 Zeichen) und speichern Sie es als das ID-Feld.

Wenn Sie mit diesen Daten in einer Datenbank zu speichern, müssen Sie nicht ein for-Schleife verwenden, um die Kollisionsprüfung zu tun, aber man konnte nicht nur eine select-Anweisung - so etwas wie

SELECT count(1) c FROM Table WHERE id = :id

Dabei gilt: id würde die neu erzeugte ID sein. Wenn c größer als 0 ist, dann wissen Sie, es ist bereits vorhanden.

Bearbeiten

Dies kann möglicherweise nicht der beste Weg, um darüber zu gehen. Aber ich werde ihm einen Schuss geben, so dass ich denke, was Sie brauchen someway der Umwandlung einer Zahl in eine einzigartige kurze Zeichenfolge ist, und das ist nicht in Folge.

Ich denke, wie Sie gesagt haben, Base64-Codierung bereits tut die Nummer kurze String-Konvertierung. Um die Sequenz Problem zu vermeiden könnten Sie eine Zuordnung zwischen dem automatisch generierten IDs zu einem gewissen „random“ Wert (eindeutige Zuordnung) haben. Dann können Sie base64 diesen einzigartigen Wert kodieren.

Sie können diese Zuordnung wie folgt generieren. Haben Sie einen temporären Tabelle speichert Werte von 1 - 10.000.000. Sortieren sie in zufälliger Reihenfolge und speichern Sie es in Ihnen Tabelle Karte.

INSERT INTO MappingTable (mappedId) SELECT values FROM TemporaryTable ORDER BY RAND()

Wo Mapping die 2 Felder-ID (Ihre automatisch generierte ID dagegen würde nachschauen) haben würde und mappedId (das ist das, was würden Sie die Base64-Codierung für erzeugen).

Wie Sie näher an 10 Millionen bekommen könnten Sie den obigen Code wieder erneut ausführen und die Werte in der temporären Tabelle wie die mit 10,000,001-20,000,000 oder etwas ändern.

Sie können eine bitweise XOR verwenden einige der Bits krabbeln:

select thefield ^ 377 from thetable;

+-----+---------+
| a   | a ^ 377 |
+-----+---------+
| 154 |     483 |
| 152 |     481 |
|  69 |     316 |
|  35 |     346 |
|  72 |     305 |
| 139 |     498 |
|  96 |     281 |
|  31 |     358 |
|  11 |     370 |
| 127 |     262 |
+-----+---------+

ich denke, das wird nie wirklich sicher sein, wie Sie nur die Verschlüsselungsmethode hinter der kurzen eindeutigen Zeichenfolge finden müssen eine ID kapern. Ist für Kollisionen in einer Schleife Überprüfung in Ihrer Einstellung wirklich so problematisch?

  

Ein MD5 einer fortlaufenden Nummer   sollte in Ordnung sein, aber ich mache mir Sorgen, dass, wenn   Sie Kürzen Ihre MD5 (was   normalerweise 128 Bit) bis zu 5-8   Zeichen, werden Sie mit ziemlicher Sicherheit   schädlich sein, es ist Fähigkeit zu handeln, als   eine einzigartige Signatur ...

Völlig richtig. Vor allem, wenn Sie Ihre 80% Kollision Chance erreichen ein verkürztes MD5 wird so gut wie jede Zufallszahl von selbst Eindeutigkeit zu gewährleisten, das heißt wertlos.

Aber da Sie eine Datenbank auf jeden Fall verwenden, warum nicht nur einen eindeutigen Index verwenden? Auf diese Weise die uniquness Prüfung (in einem viel effizienter als mit einer Schleife) von MySQL selbst erfolgt. Versuchen Sie einfach, die INSERT mit MD5-generierten Schlüssel zu tun, und wenn es fehlschlägt, versuchen Sie es erneut ...

Wenn Sie nicht ein Auto-increment-Feld verwenden können, und wollen einen absolut eindeutigen Wert, verwenden Sie UUID . Wenn Sie sich entscheiden, etwas anderes zu verwenden (außer Autoinkrement), würden Sie dumm sein, nicht auf Kollisionen zu überprüfen.

Dieser Blog-Eintrag hat etwas in der Nähe zu dem, was Sie nach.

http://kevin.vanzonneveld.net/techblog/article/create_short_ids_with_php_like_youtube_or_tinyurl/

Ein MD5 einer Inkrementierung Zahl sollte in Ordnung sein, aber ich mache mir Sorgen, dass, wenn Sie Ihre Kürzen MD5 (die in der Regel 128 Bit ist) bis auf 5-8 Zeichen, werden Sie mit ziemlicher Sicherheit schädlich sein, es ist Fähigkeit als zu handeln einzigartige Signatur ...

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