Eindeutige zeitabhängige Int64 ID wie generieren?
-
- Lazarusforum e. V.
- Beiträge: 99
- Registriert: Mo 6. Feb 2012, 17:20
- OS, Lazarus, FPC: ubuntu 10.10, L 0.9.28.2, FPC 2.4.0
- CPU-Target: x86_64
- Wohnort: Oldenburg (Oldb)
Eindeutige zeitabhängige Int64 ID wie generieren?
Hallo,
ich möchte eine ID generieren, die zunächst im RAM verwendet und später auf Platte geschrieben wird:
- signed Int64
- eindeutig
- mit jeder neuen ID aufsteigend
9.223.372.036.854.775.807 { maximaler Wertebereich signed Int64 }
9.876.543.210.987.654.321 { 19 Stellen }
J.JJJ.MMD.Dhh.mms.sxx.xzz {mögliche ID: 19 Stellen, Jahr/Monat/Tag/Stunde/Minute/Sekunde/Millisekunde/2-stelliger laufender Zähler }
Erst dachte ich, die ID einfach aus Datum und Zeit (TDateTime) zu generieren. Das funktioniert aber nicht, wenn die Uhr korrigiert bzw. zurückgestellt wird. Dann droht eine Mehrdeutigkeit bzw. die ID ist nicht stringend aufsteigend.
Wie macht Ihr so etwas? Speichert Ihr die Maximum-ID in einer Datei ab und berücksichtigt sie bei Neuvergaben?
ich möchte eine ID generieren, die zunächst im RAM verwendet und später auf Platte geschrieben wird:
- signed Int64
- eindeutig
- mit jeder neuen ID aufsteigend
9.223.372.036.854.775.807 { maximaler Wertebereich signed Int64 }
9.876.543.210.987.654.321 { 19 Stellen }
J.JJJ.MMD.Dhh.mms.sxx.xzz {mögliche ID: 19 Stellen, Jahr/Monat/Tag/Stunde/Minute/Sekunde/Millisekunde/2-stelliger laufender Zähler }
Erst dachte ich, die ID einfach aus Datum und Zeit (TDateTime) zu generieren. Das funktioniert aber nicht, wenn die Uhr korrigiert bzw. zurückgestellt wird. Dann droht eine Mehrdeutigkeit bzw. die ID ist nicht stringend aufsteigend.
Wie macht Ihr so etwas? Speichert Ihr die Maximum-ID in einer Datei ab und berücksichtigt sie bei Neuvergaben?
Liebe Grüße
turbo
turbo
Re: Eindeutige zeitabhängige Int64 ID wie generieren?
CreateGUID
http://www.freepascal.org/docs-html/rtl ... eguid.html" onclick="window.open(this.href);return false;
http://www.freepascal.org/docs-html/rtl ... tguid.html" onclick="window.open(this.href);return false;
http://www.freepascal.org/docs-html/rtl ... eguid.html" onclick="window.open(this.href);return false;
http://www.freepascal.org/docs-html/rtl ... tguid.html" onclick="window.open(this.href);return false;
-
- Beiträge: 770
- Registriert: Sa 21. Feb 2009, 13:46
- OS, Lazarus, FPC: Windows 7 (L 1.3 Built 43666 FPC 2.6.2)
- CPU-Target: 32Bit
Re: Eindeutige zeitabhängige Int64 ID wie generieren?
mögliche alternativen, alle gespeicherten werde irgendwo speichern und dann testen ob ein wert schonmal vorkam, oder nicht die systemzeit verwenden sondern irgendne zeit von nem internetserver ...
Code: Alles auswählen
Signatur := nil;
-
- Lazarusforum e. V.
- Beiträge: 99
- Registriert: Mo 6. Feb 2012, 17:20
- OS, Lazarus, FPC: ubuntu 10.10, L 0.9.28.2, FPC 2.4.0
- CPU-Target: x86_64
- Wohnort: Oldenburg (Oldb)
Re: Eindeutige zeitabhängige Int64 ID wie generieren?
Hallo theo,
danke für die Hinweise. Diese führen mich zu
http://de.wikipedia.org/wiki/Universall ... Identifier" onclick="window.open(this.href);return false;
http://tools.ietf.org/html/rfc4122#section-4.1.2" onclick="window.open(this.href);return false;
Beide Quellen stellen letztlich dieselben Probleme fest wie ich auch.
Statt der gewünschten 8 Byte (Int64) ist die Struktur 16 Byte groß.
Hat jemand anders eine Idee?
danke für die Hinweise. Diese führen mich zu
http://de.wikipedia.org/wiki/Universall ... Identifier" onclick="window.open(this.href);return false;
http://tools.ietf.org/html/rfc4122#section-4.1.2" onclick="window.open(this.href);return false;
Beide Quellen stellen letztlich dieselben Probleme fest wie ich auch.
Statt der gewünschten 8 Byte (Int64) ist die Struktur 16 Byte groß.
Hat jemand anders eine Idee?
Liebe Grüße
turbo
turbo
-
- Lazarusforum e. V.
- Beiträge: 3178
- Registriert: Di 22. Jul 2008, 19:27
- OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
- CPU-Target: 32bit x86 armhf
- Wohnort: Köln
- Kontaktdaten:
Re: Eindeutige zeitabhängige Int64 ID wie generieren?
Das Problem hast du immer, wenn du die Zeit einbeziehst, da unsere Zeitrechnung nicht so linear fortschreitet, wie man sich das immer denkt. Die wichtigsten Punkte sind:turbo hat geschrieben:Das funktioniert aber nicht, wenn die Uhr korrigiert bzw. zurückgestellt wird.
- Schaltsekunden
- Sommer-/Normalzeit
- Wie genau muss die Zeitauflösung sein? Gegebenenfalls sind die Schaltsekunden vernachlässigbar (die ein einzelner Computer ohne Zeitsynchronisation sowieso nicht mitbekommt)
- Schaltstunden lassen sich durch eine definierte Zeitzone herausrechnen oder man gibt diese mit an (CET/CEST/UTC, etc.)
- Warum brauchst du 8 Byte und nicht 16 Byte (TGUID)?
- Warum muss die ID-Zählung streng linear sein? Wird das nicht bereits durch die Zeit gewährleistet, beziehungsweise lässt sich das ohne Zeit realisieren?
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Re: Eindeutige zeitabhängige Int64 ID wie generieren?
Du könntest einen Unix-Timestamp nehmen sofern du nur jede Sekunde unterscheiden musst.
Damit ist die Id zwar auch nicht linear aber zumindest eindeutig.
Damit ist die Id zwar auch nicht linear aber zumindest eindeutig.
-
- Beiträge: 3444
- Registriert: Mo 11. Sep 2006, 10:24
- OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
- CPU-Target: X32 / X64 / ARMv5
- Wohnort: Krefeld
Re: Eindeutige zeitabhängige Int64 ID wie generieren?
8 Byte wird nicht als "eindeutig" angesehen.turbo hat geschrieben:Hallo theo,
Statt der gewünschten 8 Byte (Int64) ist die Struktur 16 Byte groß.
Ich würde die beiden Hälften als int64 auffassen und addieren. Dann hast Du 8 Byte, die vermutlich "eindeutig genug" sind.
-Michael
-
- Lazarusforum e. V.
- Beiträge: 99
- Registriert: Mo 6. Feb 2012, 17:20
- OS, Lazarus, FPC: ubuntu 10.10, L 0.9.28.2, FPC 2.4.0
- CPU-Target: x86_64
- Wohnort: Oldenburg (Oldb)
Re: Eindeutige zeitabhängige Int64 ID wie generieren?
Hallo,
vielen Dank für die Hinweise.
Ich werde es wahrscheinlich wie folgt lösen:
obere 32 Bit mit Timestamp so ähnlich wie im Format DateTimeToDosDateTime siehe http://www.freepascal.org/docs-html/rtl ... etime.html" onclick="window.open(this.href);return false;
unter 32 Bit als fortlaufender Zähler ab 1 (null ist reserviert).
Die letzte vergebene ID wird in einer Datei gespeichert.
Eine neue ist dann
obere 32 Bit: Max(gespeicherte ID;jetzt)
unter 32 Bit: gespeicherte ID+1
Damit hat man eine ca.-Zeit der Vergabe der ID in den oberen 32 Bit und eine sichere Eindeutigkeit durch fortlaufende Vergabe der untere 32 Bit. Veränderungen der Uhr werden durch Max() ausgeglichen.
Vielleicht habt Ihr noch eine Anregung, was für 32-bittige Standard-Zeitstempel existieren, die ich verwenden könnte.
vielen Dank für die Hinweise.
Ich werde es wahrscheinlich wie folgt lösen:
obere 32 Bit mit Timestamp so ähnlich wie im Format DateTimeToDosDateTime siehe http://www.freepascal.org/docs-html/rtl ... etime.html" onclick="window.open(this.href);return false;
unter 32 Bit als fortlaufender Zähler ab 1 (null ist reserviert).
Die letzte vergebene ID wird in einer Datei gespeichert.
Eine neue ist dann
obere 32 Bit: Max(gespeicherte ID;jetzt)
unter 32 Bit: gespeicherte ID+1
Damit hat man eine ca.-Zeit der Vergabe der ID in den oberen 32 Bit und eine sichere Eindeutigkeit durch fortlaufende Vergabe der untere 32 Bit. Veränderungen der Uhr werden durch Max() ausgeglichen.
Vielleicht habt Ihr noch eine Anregung, was für 32-bittige Standard-Zeitstempel existieren, die ich verwenden könnte.
Liebe Grüße
turbo
turbo
-
- Beiträge: 3444
- Registriert: Mo 11. Sep 2006, 10:24
- OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
- CPU-Target: X32 / X64 / ARMv5
- Wohnort: Krefeld
Re: Eindeutige zeitabhängige Int64 ID wie generieren?
DOS-Zeit ist ganz schlecht, weil Sommerzeit-abhängig. Du solltest in jedem Fall von der UTC-Zeit ausgehen, die keine Sommerzeit kennt.turbo hat geschrieben:obere 32 Bit mit Timestamp so ähnlich wie im Format DateTimeToDosDateTime
Siehe http://de.wikipedia.org/wiki/Koordinierte_Weltzeit" onclick="window.open(this.href);return false; ,
http://www.delphipraxis.net/66508-datet ... ieren.html" onclick="window.open(this.href);return false;
Ein ordentliches Betriebssystem mit ordentlich eingerichteter Zeit-Synchronisation (z.B. via Internet Zeit-Server) lässt den UTC-Wert nie sinken, aber u.U. stoppen.
Eine TDatetime-Variable "R" mit der UTC ist (beispielsweise) die Differenz zum 30. 12. 1899. in Tagen. (Floatingpoint-Wert)
(der 30. 12. 1899 00:00:00 ist die Basis von "NOW", warum auch immer)
R := R - C; // Das minimale für Dich relevante Datum in Tagen seit dem 30. 12. 1899 abziehen. (Floatingpoint-Wert, C = EncodeDate(YY, MM, DD) )
D := Die Differenz zwischen dem maximalen und dem minimalen für Dich relevanten Datum in Tagen berechnen (konstanter Floatingpoint-Wert)
R := R / D ist dann dein relevanter Zeitstempel in Tagen. (Floatingpoint-Wert zwischen 0.0 und 1.0)
R := R * (2^32) ist dann Dein relevanter Zeitstempel in idealer Auflösung für 32 Bit.
I := Round(R) ist dann Dein relevanter Zeitstempel in 32 Bit (DWORD)
Nun solltest Du Dir den letzten Wert merken und wenn der neue Wert nicht größer ist, eines mehr als den letzten nehmen:
if (I <= ILast) then I := ILast+1;
ILast := I;
-Michael