Lamport Clocks für Java

vorhergehende Artikel in: Java Linux Komponenten
24.02.2024

Ich habe mich in den Weihnachtsferien hingesetzt und endlich einmal ernsthaft mit sogenannten Lamport Clocks beschäftigt, mit denen man Prozesse in verteilten Systemen synchronisieren kann.

Dazu überlegte ich mir, diese von mir angestrebte Implementierung mit der Logging-Lösung logback zu integrieren, so dass der entsprechende Zeitstempel im Mapoped Diagnostic Context (MDC) automatisch gesetzt wird und in Logmessages - entsprechende Konfiguration vorausgesetzt - automatisch mit ausgegeben wird.

Dazu habe ich die Implementierung in zwei verschiedenen Modi umgesetzt: Ich schuf eine Singleton Java-Bean ebenso wie eine Implementierung einer java.time.Clock.

Zum Testen der Implementierung erstellte ich zwei Anwendungen - eine davon als Server einer Socketverbindung und eine als Client. Inhaltlich tun beide Anwendungen dasselbe: Sie senden Events an den Kommunikationspartner und empfangen Events vom jeweils anderen.

Das Senden und Empfangen wird über logback geloggt. Das Ergebnis mit dem WErt der Lamport Clock in Spalte zwei ist hier zu sejen:

2023.12.20-21:06:50,458 2 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:06:50 CET 2023
2023.12.20-21:06:50,949 3 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:06:52,005 6 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:06:52 CET 2023
2023.12.20-21:06:52,252 7 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:06:52,927 10 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:06:52 CET 2023
2023.12.20-21:06:53,134 11 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:06:53 CET 2023
2023.12.20-21:06:53,599 12 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:06:54,810 13 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:06:55,341 16 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:06:55 CET 2023
2023.12.20-21:06:56,684 17 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:06:56 CET 2023
2023.12.20-21:06:57,892 18 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:06:58,955 19 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:06:59,219 20 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:06:59,420 23 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:06:59 CET 2023
2023.12.20-21:07:00,476 24 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:00 CET 2023
2023.12.20-21:07:01,777 25 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:02,348 26 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:03,035 29 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:03 CET 2023
2023.12.20-21:07:03,047 30 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:03,150 33 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:03 CET 2023
2023.12.20-21:07:03,639 34 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:03,745 37 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:03 CET 2023
2023.12.20-21:07:03,903 38 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:03 CET 2023
2023.12.20-21:07:04,046 39 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:04,726 40 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:05,103 43 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:05 CET 2023
2023.12.20-21:07:05,639 44 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:05,949 47 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:05 CET 2023
2023.12.20-21:07:06,820 48 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:07,339 51 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:07 CET 2023
2023.12.20-21:07:07,392 52 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:07 CET 2023
2023.12.20-21:07:08,986 53 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:09,301 56 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:09 CET 2023
2023.12.20-21:07:09,713 57 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:09,888 58 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:10,398 61 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:10 CET 2023
2023.12.20-21:07:10,975 62 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:10 CET 2023
2023.12.20-21:07:11,070 63 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:11,445 66 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:11 CET 2023
2023.12.20-21:07:12,924 67 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:12 CET 2023
2023.12.20-21:07:13,078 68 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:13,744 71 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:13 CET 2023
2023.12.20-21:07:15,074 72 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:15 CET 2023
2023.12.20-21:07:15,825 73 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:15 CET 2023
2023.12.20-21:07:16,776 74 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message

und

2023.12.20-21:06:50,449 1 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:06:50,957 4 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:06:50 CET 2023
2023.12.20-21:06:52,005 5 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:06:52,252 8 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:06:52 CET 2023
2023.12.20-21:06:52,927 9 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:06:53,133 10 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:06:53,599 13 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:06:53 CET 2023
2023.12.20-21:06:54,810 14 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:06:54 CET 2023
2023.12.20-21:06:55,341 15 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:06:56,684 16 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:06:57,892 19 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:06:57 CET 2023
2023.12.20-21:06:58,955 20 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:06:58 CET 2023
2023.12.20-21:06:59,219 21 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:06:59 CET 2023
2023.12.20-21:06:59,420 22 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:00,476 23 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:01,777 26 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:01 CET 2023
2023.12.20-21:07:02,348 27 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:02 CET 2023
2023.12.20-21:07:03,035 28 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:03,047 31 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:03 CET 2023
2023.12.20-21:07:03,149 32 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:03,639 35 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:03 CET 2023
2023.12.20-21:07:03,745 36 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:03,903 37 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:04,047 40 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:04 CET 2023
2023.12.20-21:07:04,726 41 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:04 CET 2023
2023.12.20-21:07:05,103 42 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:05,639 45 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:05 CET 2023
2023.12.20-21:07:05,948 46 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:06,820 49 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:06 CET 2023
2023.12.20-21:07:07,338 50 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:07,392 51 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:08,986 54 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:08 CET 2023
2023.12.20-21:07:09,301 55 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:09,713 58 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:09 CET 2023
2023.12.20-21:07:09,889 59 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:09 CET 2023
2023.12.20-21:07:10,398 60 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:10,975 61 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:11,070 64 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:11 CET 2023
2023.12.20-21:07:11,445 65 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:12,924 66 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:13,078 69 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:07:13 CET 2023
2023.12.20-21:07:13,744 70 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:15,074 71 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:07:15,825 72 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message

Beide Logs kann man mittels cat log1.txt log2.txt |sort -b -g -k 2,2 >/tmp/sorted' nach den Lamport-Timestamps sortieren und man sieht im Ergebnis (hier abgekürzt), dass die Kommunikationsevents dadurch tatsächlich in der korrekten Ordnung angezeigt werden:

2023.12.20-21:06:50,449 1 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:06:50,458 2 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:06:50 CET 2023
2023.12.20-21:06:50,949 3 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:06:50,957 4 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:06:50 CET 2023
2023.12.20-21:06:52,005 5 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:06:52,005 6 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:06:52 CET 2023
2023.12.20-21:06:52,252 7 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:06:52,252 8 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:06:52 CET 2023
2023.12.20-21:06:52,927 9 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:06:52,927 10 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:06:52 CET 2023
2023.12.20-21:06:53,133 10 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:06:53,134 11 DEBUG [Thread-1] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:06:53 CET 2023
2023.12.20-21:06:53,599 12 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketServer run.51 - sent next Message
2023.12.20-21:06:53,599 13 DEBUG [Thread-0] d.e.scratch.util.LamportTestSocketClient run.41 - received Wed Dec 20 21:06:53 CET 2023

Man sieht allerdings auch (Timestampwert 10), dass es durchaus vorkommen kann, dass mehrere Events den gleichen Zeitstempel aufweisen - in diesem Fall handelt es sich um voneinander unabhängige Ereignisse in separaten Prozessen, bei denen eine zeitliche Ordnung beliebig und irrelevant ist.

Die beiden Klassen sind im Repository

<repository>
	<id>gitlab</id>
	<name>EL BOSSOs (https://elbosso.github.io/index.html) Maven Repository</name>
	<url>https://elbosso.gitlab.io/mvn/repository/</url>
</repository>

im Artefakt de.elbosso::util`zu finden:

<dependency>
	<groupId>de.elbosso</groupId>
	<artifactId>util</artifactId>
	<version>2.3.0-SNAPSHOT</version>
</dependency>

Die Testklassen sind im Projekt java-scratch zu finden - Ausgangspunkt ist hier LamportTestSocketClient.

Alle Artikel rss Wochenübersicht Monatsübersicht Github Repositories Gitlab Repositories Mastodon Über mich home xmpp


Vor 5 Jahren hier im Blog

  • Certstream, InfluxDB, Grafana und Netflix

    16.04.2019

    Nachdem ich vor kurzem über mein erstes Spielen mit dem certstream berichtete, habe ich weitere Experimente gemacht und die Daten zur besseren Auswertung in eine InfluxDB gepackt, um sie mit Grafana untersuchen zu können.

    Weiterlesen...

Neueste Artikel

  • Die sQLshell ist nun cloudnative!

    Die sQLshell hat eine weitere Integration erfahren - obwohl ich eigentlich selber nicht viel dazu tun musste: Es existiert ein Projekt/Produkt namens steampipe, dessen Slogan ist select * from cloud; - Im Prinzip eine Wrapperschicht um diverse (laut Eigenwerbung mehr als 140) (cloud) data sources.

    Weiterlesen...
  • LinkCollections 2024 III

    Nach der letzten losen Zusammenstellung (für mich) interessanter Links aus den Tiefen des Internet von 2024 folgt hier gleich die nächste:

    Weiterlesen...
  • Funktionen mit mehreren Rückgabewerten in Java

    Da ich seit nunmehr einem Jahr bei meinem neeun Arbeitgeber beschäftigt und damit seit ungefähr derselben Zeit für Geld mit Python arbeite, haben sich gewisse Antipathien gegenüber Python vertieft (ich kann mit typlosen Sprachen einfach nicht umgehen) - aber auch einige meiner Gründe, Python zu lieben sind ebenso stärker geworden. Einer davon ist der Fakt, dass eine Methode in Python mehr als einen Wert zurückgeben kann.

    Weiterlesen...

Manche nennen es Blog, manche Web-Seite - ich schreibe hier hin und wieder über meine Erlebnisse, Rückschläge und Erleuchtungen bei meinen Hobbies.

Wer daran teilhaben und eventuell sogar davon profitieren möchte, muß damit leben, daß ich hin und wieder kleine Ausflüge in Bereiche mache, die nichts mit IT, Administration oder Softwareentwicklung zu tun haben.

Ich wünsche allen Lesern viel Spaß und hin und wieder einen kleinen AHA!-Effekt...

PS: Meine öffentlichen GitHub-Repositories findet man hier - meine öffentlichen GitLab-Repositories finden sich dagegen hier.