Zum Inhalt springen
Deutsch

Singleton mit Lease

Der Singleton-Manager wählt standardmäßig einen Singleton allein basierend auf Cluster-Gossip. Bei Partitionen + unzureichendem Downing können beide Hälften ihren eigenen Leader wählen → zwei Singletons existieren.

Die Single-Writer-Lease verhindert das:

import { ClusterSingletonManager, KubernetesLease } from 'actor-ts';
system.spawn(
ClusterSingletonManager.props({
cluster,
typeName: 'job-scheduler',
singletonProps: Props.create(() => new JobScheduler()),
lease: new KubernetesLease({
name: 'job-scheduler-singleton',
owner: process.env.POD_NAME!,
ttlMs: 30_000,
namespace: process.env.K8S_NAMESPACE!,
}),
}),
'singleton-manager-job-scheduler',
);

Jetzt spawnt der Manager den Singleton erst nach dem Erwerb der Lease. Zwei Manager, die gleichzeitig Leadership beanspruchen, liefern sich ein Rennen um die Lease; nur einer gewinnt.

Lease-Backendmanager_Bmanager_ALease-Backendmanager_Bmanager_ANetzwerkpartition —sowohl A als auch B sehen sich als LeaderRennen — atomares CASPartition heilt — Gossip konvergiertLease erwerbenLease erwerbenErfolgFehlerspawne Singletonbleibe passivonLost feuert auf der zurückgetretenen Seite

Das Lease-Backend (K8s-API-Server) liefert die atomare Exactly-One-Holder-Garantie — jenseits der eventuellen Konsistenz von Gossip.

ClusterSingletonManager.props({
cluster,
typeName,
singletonProps,
lease, // ← optionale Lease
acquireRetryIntervalMs: 5_000, // Default — Retry nach fehlgeschlagenem Acquire
});

Lease ist dieselbe Abstraktion wie bei Coordination — InMemoryLease für Tests, KubernetesLease für Produktion.

SetupSingleton-Einzigartigkeitsgarantie
Kein Downing, keine LeaseBest-Effort. Partitionen = doppelte Singletons.
Nur Downing-StrategieStark in stabilen Netzwerken.
Downing + LeaseParanoid-sicher. Beide Invarianten erzwungen.

Für Singletons, bei denen Doppelausführung echten Schaden anrichten würde (Kunden doppelt belasten, Events doppelt veröffentlichen), nutze beides.

// Innerhalb des Managers (vom Framework verwaltet):
lease.onLost((reason) => {
// Stoppe den Singleton; retry acquire nach acquireRetryIntervalMs
});

Wenn die Lease widerrufen wird (TTL abgelaufen, anderer Halter hat sie übernommen):

  • Der Manager stoppt den Singleton sofort — kein geordnetes Drainen.
  • Der postStop des Singletons läuft.
  • Der Manager versucht Acquire periodisch erneut.

Bedeutet: wenn das Lease-Backend kurz hickst und sie kurzfristig widerruft, startet der Singleton neu während der Erholung — gleicher Effekt wie ein kurzer Actor-Neustart.

K8s-API-Ausfall → keine Lease-Renewals → Singleton verliert irgendwann die Lease
→ Singleton stoppt überall
→ kein Singleton verfügbar, bis K8s-API sich erholt

Das Lease-Backend wird zum SPOF. Für typische Cluster ist die K8s-API-Uptime viel höher als die des restlichen Systems, aber das ist eine echte Überlegung. Plane den seltenen Fall ein.

A's Lease hat TTL 30s.
A stürzt ab — kein Renew passiert.
Nach 30s läuft die Lease ab.
B erwirbt + spawnt Singleton.

Failover-Fenster = Lease-TTL. Konfigurierbar über das ttlMs-Feld der Lease.

Kürzere TTL = schnelleres Failover, aber mehr Renew-Verkehr. Typisch: 15-30 Sekunden.

Sekunden 0-30: A's Lease noch gültig (er ist abgestürzt, aber TTL läuft noch)
B kann nicht acquiren; nirgendwo ein Singleton
Nachrichten an den Singleton landen in Dead Letters
Sekunden 30+: B erwirbt; Singleton spawnt
Wenn Singleton ein PersistentActor ist, läuft Recovery
Nachrichten werden wieder verarbeitet

Während der Lücke scheitern Nachrichten an den Singleton — sie routen zu einem gestoppten Manager und landen in Dead Letters.

Für Workloads, bei denen das inakzeptabel ist, erwäge:

  • Niedrigeres TTL (15 s gibt schnelleres Failover, mehr Renewals).
  • Pufferung beim Sender — der Singleton-Proxy kann während der Lücke puffern und danach erneut senden.
  • Andere Architektur — Singletons sind inhärent seriell-bei-Failover.
Singleton + LeaseSharding + Lease
Was geschützt wirdSingleton-EinzigartigkeitKoordinator-Einzigartigkeit
Was bei Lease-Verlust stopptDer Singleton-ActorAllokationen des Koordinators
Failover-Fenster-KostenSingleton unverfügbarNeue Shard-Allokationen werden in Warteschlange gestellt
Bestehende Arbeit während FailoverPausiertLäuft für bereits allokierte Shards weiter

Singleton-Failover ist disruptiver — der Singleton ist die Workload. Sharding-Failover betrifft nur neue Allokationen — existierende Entities verarbeiten weiter.