Was ist eine Race Condition?

Wir hatten in einem Projekt den Fall, dass mehrere Systeme Kundendaten in eine MQ geschrieben haben. Diese Kundendaten mussten am Zielsystem natürlich so schnell wie möglich verarbeitet werden. Jetzt gab es den Spezialfall, dass, wenn ein Kunde namens Altair im Zielsystem noch nicht existierte, dieser erstellt werden sollte.

Das System Kuchen schickte also seinen Kunden Altair in das Zielsystem. Dieses stellte fest, dass es den Namen noch nicht gab, und erstellte einen Kundeneintrag für diesen. Traditionsgemäss brauchte dieses Eröffnen eines Kundenkontos dabei einige Zeit, das im Hintergrund viele Dinge beachtet werden mussten.

Was passierte nun aber, wenn das System Müesli ebenfalls den Kunden Altair auf den Weg schickte, zeitgleich wie das System Kuchen? Dann entsteht eine sogenannte Race Condition, ein Zeitrennen dieser beiden Aufträge.

Warum ist das ein Problem?

Nun, wenn die beiden Aufträge den exakt gleichen Kunden erstellen würde, wäre das nicht so schlimm. Was ist jetzt aber, wenn eine ihre Daten aus unterschiedlichen Orten (etwa verschiedene Benutzeroberflächen) holen? Dann gibt es vielleicht, je nachdem welches System gewinnt, einen männlichen oder einen weiblichen Altair.

Oder ein falscher Kontostand? Nicht gut…

Noch schlimmer wäre es, wenn bei der gleichzeitigen Verarbeitung dieser Kundeneröffnungen ein Betrag zuerst abgefragt werden müsste, bevor man ihn wieder in die Datenbank schreiben würde.

Wenn etwa das System Kuchen zuerst den existierenden Kunden Ezio aus der Datenbank liest, dessen Kontostand abfragt und diesen dann um 20 Franken erhöht. Aus ursprünglich 50 Franken wird so ein Betrag von 70 Franken, welcher wieder in die Datenbank geschrieben wird.

Liest jetzt aber das System Müesli zur exakt gleichen Zeit die Daten, erhöht diese um 30 Franken auf 80 Franken, und schreibt diese in die Datenbank, nachdem System Kuchen seinen Arbeit gemacht hat, steht am Ende ein Betrag von 80 Franken – statt der Summe von 50 + 20 + 30 = 100 Franken.

Sehr gefährlich!

Okay und was macht man dagegen?

In der Programmierung gibt es viele Mechanismen, die sich diesem Problem annehmen. Wer sich dafür interessiert, wird früher oder später über die Begriffe Threadsafe, Concurrency oder Synchronize stolpern.

Das ist aber wieder eine ganz andere Geschichte…

Was ist DevOps?

DevOps ist ein Konzept, welches aus zwei Trends heraus entstanden ist: Zum einen gibt es den Trend namens Agile Systemadministration oder Agile Operations, welche das Ziel verfolgen, agile Konzepte auch den IT Betrieb zu bringen. Zum anderen steht dahinter die Idee, einen Nutzen daraus zu gewinnen, dass die Entwicklung und der Betrieb möglichst eng miteinander arbeiten, sei das entweder beim Erstellen oder beim betreiben einer Dienstleistung. Diese Zusammenarbeit soll über den gesamten Applikaitonslebenszyklus – oder moderner Servicelebenszyklus stattfinden, vom Design zur Entwicklung und Wartung einer Applikation.

Dev meint dabei nicht nur den bekannten Entwickler, sondern jede Person, die irgendwie an der Entwicklung einer Appliation beteiligt ist. Ops steht für alle möglichen Jobs im Betrieb: Systemadministrator, Datenbankadministratoren, Netzwerktechniker, Sicherheitsspezialisten etc.

Schlussendlich ist DevOps aber mehr als Entwicklung und Betrieb, mehr als die Tools und Prozesse, die dahinterstehen. Es steht für eine Philosophie, eine Einstellung, Dinge anders zu machen als in der Vergangenheit. Es ist das Schaffen einer Kultur, in der die Entwickler mit dem Betrieb zusammenarbeiten, immer mit dem Ziel, eine möglichst gute Software abzuliefern und am Laufen zu halten. Und alle Beteiligten arbeitet zusammen, um dieses Ziel zu erreichen.

Das Umdenken in der agilen Revolution

Bevor Agile unsere Welt kam schienen die Rollen klar verteilt: Die Devs waren die Macher, die Ersteller der Software, während die Ops die Personen waren, die sich um die Applikation in der Wartung gekümmert haben. Die Industrie hat aber festgestellt, dass diese zwei Rollen durchaus Synergieeffekte für sich nutzen können, wenn sie zusammenarbeiten.

Dieser Gedankenanstoss kam auch aus der agilen Ecke: Dort wird bis heute die Zusammenarbeit als eines der höchsten Werte gepriesen. Und das nicht nur zwischen diesen beiden, sondern zwischen allen Rollen. Gemeinsam soll in kurzen Iterationen das Produkt beziehungsweise das Inkrement stetig verbessert werden. Aus agiler Sicht macht es nur Sinn, wenn man die Interaktion eines Systems mit deren Umsystemen gemeinsam betrachtet und die Applikation als Ganzes betrachtet, statt nur den Code.

 Entwickler werden sich dabei vermehrt mit dem Thema der virtuellen Maschinen beschäftigen, während die Leute im Betrieb sich mit automatisierten Tests auseinandersetzen. Das ganze läuft dann bestenfalls unter einem Schirm von gemeinsamen Messzahlen (KPI = Key Performance Indicators).

Developer und Operations-Leute werden weiterhin bestehen

Genauso wie es unrealistisch isch, dass in einem Scrum Team jede Person ein Software Architekt ist, ist es nicht möglich, dass Leute im Betrieb plötzlich die gesamte Entwicklung übernehmen oder umgekehrt. Es ist aber sehr von Vorteil, wenn die Leute im Betrieb die Entwickler verstehen und auch die Entwickler ein gewisses Skill-Set haben, um betriebliche Herausforderungen zu meistern – Nicht zuletzt, wenn es einen Stellvertreter braucht, weil eine Person im Betrieb vier Wochen in die Ferien geht.

Wie starre Prozesse eine Firma in die Knie zwingen können

Wir hatten also dieses neue Projekt, welches hunderttausende von Dateien verarbeiten musste. Das Problem war, dass wir nicht sicher sein konnten, wie schnell die Performance im laufenden Betrieb schlussendlich sein würde. Und in den Testumgebungen hatten wir nicht genügend Testdaten, um die Auslastung im Produktionsumfeld auch nur annähernd zu erreichen.

Das war damals eine Java Spring JMS Webapplikation. Wie es zu deren Natur gehört, hatten wir eine Konfigurationsdatei, in der wir etliche Parameter (Anzahl Threads etc.) einstellen konnten.

Nun waren wir aber alles andere als „Agile“ aufgestellt. Wir hatten jeweils nur wenige Releases pro Jahr. Natürlich gab es einen Prozess für ausserordentliche Lieferungen: Wenn es irgendwo brannte, musste man schnell reagieren und eventuelle Bugs beseitigen. Diese Prozesse gingen aber relativ lange und brauchten immer eine Unmenge von administrativem Aufwand. Und wenn man etwas liefern/beheben wollte, war das meistens ein recht negatives Erlebis. Man musste sich quasi das Recht erkämpfen, doch bitte die Software korrigieren zu können, damit der Kunde die Applikation funktionsgerecht verwenden konnte.

Verstehen Sie mich nicht falsch. Natürlich muss man mit allen Mitteln (Unittests, automatisierten Integrationstests etc.) verhindern, dass eine solche Situation entsteht. Doch eine solche Abneigung gegenüber Veränderung empfand ich als sehr lästig. Und heutige Informatiksysteme sind so gross, komplex und unüberschaubar geworden und miteinander verwoben, dass es durchaus Folgereaktionen geben kann, die man so nicht erwartet hätte. Nur schon die Vorstellung, man könnte alle Folgereaktionen und Abhängigkeiten einer Einlieferung wissen, ist absurd.

Wir wollten also Fehler beheben. Wir wollten auch eine möglichst gute Performance hinkriegen. Doch in der Realität haben wir die Parameter der Konfigurationsdatei initial bestimmt, so gut wir diese verstanden haben, und nachfolgend nur noch einmal angepasst. Wenn man jedesmal einen Marathon laufen muss, um einen Wert in einer Datei zu ändern, lässt man es irgendwann sein und hofft, dass doch alles noch gut kommt.

Ich hätte mir gewünscht, dass wir die Parameter öfters hätten ändern können – Und zwar in kleinen Schritten, um zu verstehen, welche Parameter wirklich etwas an der Performance verändern und das System beschleunigen oder verlangsamen. Aber was wir uns auch überlegten, jeder Schritt endete in einem administrativen Prozess, bei denen wir höchstens zwischen „mühsam“ und „einigermassen erträglich“ haben wählen können.

Wenn ich dann höre, dass in „fully agile Projekten“ eine unkomplizierte Anpassung der Produktion jeden Tag möglich ist, werde ich schon ein wenig neidisch. Ob es in der Realität in agilen Projekten wirklich so unkompliziert vonstatten geht?