Cache im Überblick
Das Cache-Interface ist der opportunistische Key/Value-Cache
des Frameworks. Drei Operationen decken ~95 % der realen Fälle ab:
get, set, atomares Inkrement, set-if-absent, delete.
Genutzt von:
- Response-Cache-Middleware — Caching von GET-Responses.
- Rate-Limit-Middleware — Zähler pro Key.
- Idempotency-Key-Middleware — Write-Dedup.
- CachedSnapshotStore — Read-Through-Cache für Snapshots.
Das Interface
Abschnitt betitelt „Das Interface“interface Cache { get<V>(key: string): Promise<Option<V>>; set<V>(key: string, value: V, ttlMs?: number): Promise<void>; incr(key: string, ttlMs?: number): Promise<number>; setIfAbsent<V>(key: string, value: V, ttlMs?: number): Promise<boolean>; delete(...keys: string[]): Promise<void>; mget<V>(keys: string[]): Promise<Map<string, V>>; mset(entries: Array<[string, unknown, number?]>): Promise<void>;}Kleine Oberfläche — keine Pattern-Scans, kein Pub/Sub (der Cluster hat sein eigenes Pub/Sub).
Drei Backends
Abschnitt betitelt „Drei Backends“| Backend | Einsatz |
|---|---|
InMemoryCache | Single-Pod / Tests. In-Process-Map. |
RedisCache | Multi-Pod-Produktion. Umschließt ioredis. |
MemcachedCache | Multi-Pod, wo Memcached passt. Umschließt memjs. |
Wähle nach Deployment-Form:
- Single-Pod — InMemoryCache. Schnell, keine extra Peer-Deps.
- Multi-Pod mit bereits vorhandenem Redis — RedisCache.
- Multi-Pod mit bereits vorhandenem Memcached — MemcachedCache.
- Multi-Pod ohne Präferenz — RedisCache. Mehr Features (Pub/Sub, Persistenz usw.) und das größere Ökosystem.
Opportunistische Semantik
Abschnitt betitelt „Opportunistische Semantik“Caches sind per Design verlustbehaftet. Ein get, das
None zurückgibt, heißt “nicht gecacht” — Aufgabe des Aufrufers
ist, auf die Quelle der Wahrheit zurückzufallen:
const cached = await cache.get<User>(`user:${id}`);if (cached.isSome()) return cached.value;
const user = await db.users.findById(id); // ← Quelle der Wahrheitawait cache.set(`user:${id}`, user, 60_000);return user;Wenn set fehlschlägt (Redis down, Netzwerk-Aussetzer), bleibt
der Cache leer — aber der Aufruf liefert trotzdem die richtige
Antwort (die Quelle der Wahrheit wurde konsultiert).
Cache-Implementierungen liefern bei transienten Fehlern Defaults zurück, statt zu werfen. Missbrauch (schlechte TTL, malformed Value) wirft.
TTL-Semantik
Abschnitt betitelt „TTL-Semantik“await cache.set('key', value, 60_000); // läuft in 60s abawait cache.set('key', value); // kein Ablauf- Mit
ttlMs— Eintrag läuft nach dem Fenster ab. - Ohne — Eintrag bleibt, bis er evicted wird (LRU bei InMemoryCache; Backend-Policy bei Redis / Memcached).
Die meisten Einsätze: immer eine TTL setzen. Einträge ohne TTL wachsen bis zur Eviction; explizite TTLs sind vorhersehbar.
Atomares Inkrement
Abschnitt betitelt „Atomares Inkrement“const count = await cache.incr(`requests:${userId}`, 60_000);if (count > 100) throw new Error('rate limit');incr liefert den neuen Zählerstand nach dem Inkrement.
Wenn ttlMs gesetzt ist UND der Zähler gerade erst erzeugt wurde
(count === 1), wird die TTL gesetzt.
Wird von der Rate-Limit-Middleware für Fixed-Window-Counter genutzt.
Set-if-absent
Abschnitt betitelt „Set-if-absent“const got = await cache.setIfAbsent('lock:key', 'me', 5_000);if (got) { // Ich habe das Rennen gewonnen; mach die Arbeit} else { // Jemand anderes hat es}Atomarer Schreibvorgang im CAS-Stil. Wird von der Idempotency- Key-Middleware genutzt, um “ich bin der erste Request mit diesem Key” zu erkennen.
Bulk-Operationen
Abschnitt betitelt „Bulk-Operationen“const users = await cache.mget<User>(['user:1', 'user:2', 'user:3']);// → Map<string, User> — fehlende Keys nicht enthaltenRound-Trip-Optimierung. Entscheidend für Hydratation geteilter Entitäten nach einem Sharding-Rebalance — den State jeder aktiven Entität in einem Redis-Call statt N holen.
mset ist das Gegenstück:
await cache.mset([ ['user:1', user1, 60_000], ['user:2', user2, 60_000],]);Wann den Cache NICHT nutzen
Abschnitt betitelt „Wann den Cache NICHT nutzen“Wohin als Nächstes
Abschnitt betitelt „Wohin als Nächstes“- In-Memory-Cache — das Default-Backend.
- Memcached-Cache — für Memcached-Deployments.
- Redis-Cache — für Redis- Deployments.
- Response-Cache-Middleware — der primäre Konsument.
Die Cache-API-Referenz deckt das
volle Interface ab.