Eindeutige zeitabhängige Int64 ID wie generieren?

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
turbo
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?

Beitrag von turbo »

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?
Liebe Grüße
turbo

Benutzeravatar
theo
Beiträge: 10904
Registriert: Mo 11. Sep 2006, 19:01

Re: Eindeutige zeitabhängige Int64 ID wie generieren?

Beitrag von theo »

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;

MAC
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?

Beitrag von MAC »

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;

turbo
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?

Beitrag von turbo »

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?
Liebe Grüße
turbo

Socke
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?

Beitrag von Socke »

turbo hat geschrieben:Das funktioniert aber nicht, wenn die Uhr korrigiert bzw. zurückgestellt wird.
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:
  • Schaltsekunden
  • Sommer-/Normalzeit
Um das Problem zu lösen, musst du dir noch weitere Fragen beantworten (uns auch, damit wir dein Problem besser verstehen und dir helfen können):
  • 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

DiBo33
Beiträge: 334
Registriert: Do 11. Okt 2007, 18:01

Re: Eindeutige zeitabhängige Int64 ID wie generieren?

Beitrag von DiBo33 »

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.

mschnell
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?

Beitrag von mschnell »

turbo hat geschrieben:Hallo theo,
Statt der gewünschten 8 Byte (Int64) ist die Struktur 16 Byte groß.
8 Byte wird nicht als "eindeutig" angesehen.

Ich würde die beiden Hälften als int64 auffassen und addieren. Dann hast Du 8 Byte, die vermutlich "eindeutig genug" sind.

-Michael

turbo
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?

Beitrag von turbo »

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.
Liebe Grüße
turbo

mschnell
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?

Beitrag von mschnell »

turbo hat geschrieben:obere 32 Bit mit Timestamp so ähnlich wie im Format DateTimeToDosDateTime
DOS-Zeit ist ganz schlecht, weil Sommerzeit-abhängig. Du solltest in jedem Fall von der UTC-Zeit ausgehen, die keine Sommerzeit kennt.

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

Antworten