excache

Eine Cache-Schicht in Elixir, die das OTP-Aktormodell nutzt. Nebenläufig, widerstandsfähig gegen Ausfälle einzelner Prozesse, mit echten Tests.

excache
TL;DR

Eine Cache-Schicht in Elixir auf dem OTP-Aktormodell. Nebenläufigkeit ohne Races, Widerstandsfähigkeit gegen den Ausfall einzelner Prozesse und echte Tests. Der Kniff besteht darin, dafür zu sorgen, dass das Umkippen eines Elements nicht den Rest mitreißt.

Einführung

Ein zwischen vielen Threads geteilter Cache ist eines der klassischen schwierigen Nebenläufigkeitsprobleme. excache zeigt, dass Elixir und das OTP-Aktormodell dieses Problem in etwas verwandeln, das man ohne Locks und ohne die leise Angst vor einem Deadlock bewältigen kann. Statt gegen geteilten Speicher zu kämpfen, verlagern Sie den Zustand dorthin, wo niemand parallel darauf zugreift.

Es ist ein Projekt über zwei Eigenschaften zugleich: Nebenläufigkeit ohne Races und Widerstandsfähigkeit gegen Ausfälle. Beide entspringen derselben OTP-Philosophie, in der der Zustand in einem Prozess lebt und Fehler nicht unter den Teppich gekehrt, sondern isoliert werden.

Das Aktormodell dreht das Nebenläufigkeitsproblem um

In den meisten Sprachen bedeutet ein zwischen Threads geteilter Cache Locks, Mutexe und die leise Angst vor einem Deadlock. Elixir geht einen anderen Weg: Jeder Zustand lebt in einem Prozess, der eine Nachricht auf einmal bearbeitet. Statt geteilten Speicher zu sperren, senden Sie eine Nachricht und bekommen eine Antwort.

Das Rennen um die Datenstruktur existiert schlicht nicht, weil niemand parallel darauf zugreift. Dieselbe Garantie, die man in anderen Sprachen mit Mutexen erkämpfen muss, ist hier eine kostenlose Eigenschaft des Modells.

cache.ex · bash
def handle_call({:get, key}, _from, state) do
  {:reply, Map.get(state, key), state}
end

Let it crash statt Defensive

In OTP wickeln Sie nicht jede Operation in einen defensiven Block gegen Ausfälle. Stattdessen lassen Sie den Prozess abstürzen, und ein Supervision-Tree holt ihn in einem sauberen Zustand zurück. Es ist das Gegenteil defensiver Programmierung: Sie verstecken den Fehler nicht, Sie lassen ihn einen Prozess umwerfen und vertrauen darauf, dass die Supervision ihn wieder aufbaut.

excache stützt sich direkt darauf: Wenn ein Cache-Prozess stirbt, wirft das nicht die ganze Schicht um, denn die anderen Prozesse leben unabhängig. Der beschädigte Zustand verschwindet mit dem Prozess, und sein Nachfolger startet sauber, statt kaputte Daten mitzuschleppen.

➜
Tipp

Der Test dieser Eigenschaft besteht darin, dass Sie bewusst einen Prozess mitten im Verkehr töten und prüfen, ob die Schicht weiter antwortet. Wenn der ganze Cache mit einem Prozess untergeht, ist der Supervision-Tree falsch zusammengesetzt, und ein guter Test fängt das sofort ab.

Das ist ein kontrafaktischer Test in reinster Form: Sie prüfen nicht, ob das System funktioniert, wenn alles gut läuft, sondern ob es den Ausfall überlebt, den es überleben soll. Ein Test, der nie einen Prozess sterben sieht, beweist keinerlei Widerstandsfähigkeit.

Widerstandsfähigkeit als Eigenschaft, nicht als Notlösung

Das Ergebnis ist eine Schicht, die Ausfälle als normalen Betriebszustand behandelt und nicht als Ausnahme, die zu flicken ist. Nebenläufigkeit ist von vornherein sicher, weil niemand Speicher teilt, und ein einzelner Ausfall bleibt lokal, weil die Supervision nur das wieder aufbaut, was gefallen ist.

Die Eigenschaften der Schicht und woraus sie folgen

EigenschaftWoraus sie folgt
Keine Racesein Prozess, eine Nachricht auf einmal
Keine LocksKommunikation über Nachrichten
FehlerisolationZustand im Prozess eingeschlossen
Rückkehr zum sauberen Zustandder Supervision-Tree

Weitere Projekte

Weitere Projekte aus derselben Kategorie - sehen Sie, wie wir ähnliche Herausforderungen angehen.

Haben Sie ein ähnliches Projekt?

Melden Sie sich - ein Angebot ist kostenlos und kommt innerhalb einer Stunde.