15-06-2018 door: Patrick Diks
Ik ga snel weer eens een blog schrijven zou ik lang geleden wel eens gezegd kunnen hebben. Dat zou dan inconsistent zijn met wat er hier op de site te zien is geweest.
Inconsistent zien we als een vies woord, het is een soort onwaarheid. Het ene zegt dit en het andere dat, er is er een die liegt!
In dit specifieke geval zou het meer een onverstandige belofte zijn, maar het had ook een technische reden kunnen hebben. Deze blog zou ik misschien een paar maanden geleden al geschreven kunnen hebben en vanwege een defecte communicatie nooit doorgekomen zijn. Wat je ziet is dan niet in sync met wat er geschreven is. Zou dat gebeurd zijn en de communicatie was hersteld dan zou je ineens een nieuwe blogpost met een datum ver in het verleden kunnen zien. Ziet er niet heel betrouwbaar uit, maar is in dit geval ook niet ernstig.
Dit soort situaties komen steeds vaker voor in systemen. Niet in de tijd van maanden zoals in dit (overigens zuiver hypothetische) voorbeeld, maar eerder in seconden of minuten. Dit heeft te maken met de meer gedistribueerde systemen die tegenwoordig ontwikkeld worden. De achtergrond zit hem in het zogenaamde ‘twee generaals probleem‘.
Het probleem is dat de generaals geen aanval kunnen coördineren als ze niet zeker zijn dat hun communicatie snel en volledig is. De generaals zijn in ons vakgebied computers en de communicatie loopt over een netwerk. Wil je zorgen dat alle betrokken systemen op elk punt in tijd hetzelfde laten zien dan is de consequentie wachten. Binnen een fysieke machine kan dat en dat is ook wat we gewend zijn te doen. Over een netwerk kan er verlies zijn en met gedistribueerde systemen als microservices kun je wel eens niet weten hoe vaak een stuk software waar draait.
Het gevolg is inconsistentie. Bah, ondanks de uitleg toch nog steeds niet leuk.
Je bent bijvoorbeeld een huisje aan het boeken voor de vakantie en even later blijkt dat de periode toch niet beschikbaar was. Van een systeem vinden we dit al snel een defect, maar in de buitenwereld speelt hetzelfde en zien we het als normaal. In een restaurant bestel je de dagschotel tonijn en even later komt de ober terug met de mededeling dat zojuist het laatste stuk tonijn gebruikt is en dat het toch iets anders uitzoeken wordt.
De vroegere systemen hadden als nadeel dat als het uitviel je niets had of je moest hele dure oplossingen voor failover en disaster recovery inrichten. Ook werd het heel snel heel duur als je op wilde schalen. Gedistribueerde systemen garanderen betere availability, maar er kunnen zogenaamde partitions ontstaan als er een een onderdeel niet bereikbaar is. Deze partitions zijn dan onderling niet meer consistent. We leveren dus consistentie in voor beschikbaarheid en in het kielzog daarbij winnen we snelheid en schaalbaarheid.
Om het voordeel te pakken en zo min mogelijk last te hebben van de consequenties is het zaak om gedistribueerde systemen slim op te zetten. Enerzijds vanuit de functionele hoek. Hoe ga je om met de verschillende inconsistente situaties? Hier is het zaak om zoveel mogelijk naar de buitenwereld te ontwerpen en vergelijkbare afhandelingen voor het systeem te bedenken.
Daarnaast moet de inconsistentie tijdelijk blijven, uiteindelijk moet alles weer kloppen. De oplossing daarvoor is werken met een patroon als ‘event sourcing’. Als je alle handelingen in de tijd wegschrijft in een centrale log dan is daaruit altijd weer te bepalen hoe elke situatie uitpakt ook al komt er iets te laat door. Zo kunnen de systemen op de achtergrond zelfherstellend zijn.
Stel je bijvoorbeeld de situatie van een bibliotheek voor. Je kunt in een database bijhouden welk boek aan wie uitgeleend is, maar als het terugbrengen eens niet goed verwerkt is blijft het boek uitgeleend staan. Als je het dan opnieuw uitleent staat de nieuwe klant geregistreerd bij het boek. Komt daarna de actie van het terugbrengen door dan kun je niet meer goed zien of het te laat ingeleverd is. Werken met een log als basis geeft je dan de mogelijkheid om elk punt in de tijd te reconstrueren en af te handelen.
De eigenlijke persistentie (opslag) ligt bij event sourcing niet meer zoals gebruikelijk in een database, maar in deze log. Dit levert weer andere voordelen. Dat is wellicht iets voor een andere keer, maar het kan even duren voor dat doorkomt.