Download the PHP package moselwal/keyvalue-store without Composer
On this page you can find all versions of the php package moselwal/keyvalue-store. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Informations about the package keyvalue-store
KeyValue Store — TYPO3 Extension
Redis/Valkey integration for TYPO3 14: cache backend, session backend,
distributed locking. Production-ready Sentinel discovery, TLS, and mTLS.
Built-in override pack against TYPO3 Core's legacy Redis anti-patterns
(KEYS, blocking DEL).
Components
| Component | Class | Drop-in for |
|---|---|---|
| Cache backend | KeyValueBackend |
TYPO3\CMS\Core\Cache\Backend\RedisBackend |
| Session backend | KeyValueSessionBackend |
TYPO3\CMS\Core\Session\Backend\RedisSessionBackend |
| Locking strategy | KeyValueLockingStrategy |
LockingStrategyInterface (registered automatically) |
Installation
text
Requirements
- PHP 8.5+
- TYPO3 14.x
ext-redis>= 6.3 (phpredis with the v6 constructor-config API, Sentinel resolver, TLS context, and decorrelated-jitter backoff)- Redis 4.0+ or Valkey (UNLINK is required for the v4.2.0 override pack)
Configuration
The cleanest path is via moselwal/typo3-config —
its autoconfigureCaching(), session-binding, and locking helpers wire
all three components consistently. Manual configuration is supported
and documented below.
Cache backend
Session backend
text
Locking strategy
The locking strategy registers via TYPO3's LockFactory configuration:
What v4.x does differently from TYPO3 Core's RedisBackend
The KeyValueBackend extends RedisBackend and overrides four
operations to drop server-side anti-patterns. The other operations
(get, set, has, remove, findIdentifiersByTag) are inherited
verbatim — Core already pipelines tag tracking there, so there is
nothing to add.
| Operation | TYPO3 Core | KeyValueBackend (v4.3.0) |
|---|---|---|
set() |
SETEX + SMEMBERS + (optional MULTI/PIPELINE) tag diff | Single Lua EVAL (atomic, 1 roundtrip) |
flush() |
KEYS prefix* + DEL (event-loop block for all clients) |
SCAN + UNLINK batches (server stays responsive) |
flushByTag() / flushByTags() |
N× sequential flushByTag() fan-out |
One sUnion + one pipelined UNLINK |
collectGarbage() |
KEYS identTags:* |
SCAN-loop |
| Connection | pconnect() only, no Sentinel/TLS |
KeyValueConnectionFactory (Sentinel resolver, mTLS, backoff) |
| Serializer | hard-coded PHP-native | configurable: php / igbinary / none / auto |
Additionally:
lazy=trueis the default — the TCP/TLS handshake is deferred to the first command. Bootstrap of 11 cache backends drops from ~25 ms to ~0.07 ms on a real mTLS Valkey setup.OPT_SCAN = SCAN_RETRYis set on every connection so phpredis retries empty SCAN pages internally instead of returningfalseto the caller (a well-known phpredis 6.x footgun).
Bench (real, container-side against Valkey/mTLS, phpredis 6.3.0)
| Operation | Core / v4.0.x | v4.3.0 | Δ |
|---|---|---|---|
| Bootstrap 11 caches | 25.1 ms | 0.07 ms | 381× |
getAll() 500 sessions |
37.2 ms | 1.5 ms | 24.6× |
renew() (session fixation) |
360 µs | 161 µs | 2.2× |
| Retry-Backoff (2 failures) | 162 ms | 31 ms | 5.1× |
set() 1 tag |
353 µs | 264 µs | 1.3× |
set() 5 tags |
421 µs | 266 µs | 1.6× |
set() 10 tags |
421 µs | 286 µs | 1.5× |
set() 20 tags |
582 µs | 299 µs | 1.9× |
flushByTags(10 tags) |
4.1 ms | 1.2 ms | 3.3× |
flush(10 k keys) |
7.4 ms | 9.5 ms | −30 % wallclock, no event-loop block |
collectGarbage(5 k keys) |
1.4 ms | 2.8 ms | −50 % wallclock, no event-loop block |
The flush() and collectGarbage() overrides are intentionally
slower wallclock-wise for the caller. The trade-off is server-side
fairness: while KEYS runs, every other client in the Valkey
instance is blocked. With SCAN, the server can interleave other
clients between batches — for a multi-site, multi-pod setup that is
the more important property. Neither path is a hot-path operation
(flush() is BE/CLI-triggered; collectGarbage() runs in the
scheduler tick).
Session backend internals
KeyValueSessionBackend is a from-scratch implementation of TYPO3's
SessionBackendInterface. Notable choices:
- JSON serialisation for session payloads (not PHP-native) so
records remain debuggable with
valkey-cli - WATCH / MULTI / EXEC on
update()with bounded retries — optimistic concurrency, two-tab login is safe - Lua EVAL for
renew()— atomic GET/SETEX/DEL so concurrent updates cannot be lost during the rename getAll()via SCAN + MGET instead of SCAN + N× GET — 24.6× faster on 500 sessions
Locking strategy internals
KeyValueLockingStrategy uses the Lua-EVAL + BLPOP pattern recommended
by the Redis docs:
tryLock()is a single atomicSET key value NX EX ttlwait()blocks via server-sideBLPOPon a signal list — no client-side pollingunlockAndSignal()runs a Lua script that atomically verifies ownership (GET), releases (DEL), and wakes one waiter (RPUSH + EXPIRE)
Architecture
All three TYPO3-facing components route their phpredis instantiation
through KeyValueConnectionFactory so Sentinel, TLS, mTLS, and the
phpredis 6.x backoff config are configured in exactly one place.
Development
Tooling lives in moselwal/dev. Common commands:
text
Tests gated with #[RequiresPhpExtension('redis')] skip locally when
ext-redis is missing and run in CI / dev containers where it is
installed.
Dependencies
| Package | Type | Purpose |
|---|---|---|
php ^8.5 |
Required | Language baseline |
typo3/cms-core ^14.0 |
Required | TYPO3 core |
ext-redis >= 6.3 |
Required | phpredis with v6 constructor API |
moselwal/dev ^5.2 |
Dev | Shared QA tooling (phpstan, cs-fixer, etc.) |
Related
moselwal/typo3-config— Fluent TYPO3 config API withautoconfigureCaching()that wires this packagemoselwal/cluster-file-backend— Pod-local cache backend that uses this package'sKeyValueBackendas its metadata storage layer
Serializer
KeyValueBackend defaults to PHP-native serialization (SERIALIZER_PHP).
Operators can opt into other phpredis serializers via the serializer
option:
| Value | Behaviour |
|---|---|
'php' (default) |
PHP-native, BC-safe, identical to v4.2.0 |
'igbinary' |
igbinary when ext-igbinary is loaded; falls back to PHP-native with a notice otherwise |
'none' |
No phpredis-layer serialization; the caller serializes |
'auto' |
igbinary if loaded, php otherwise (not the default, see below) |
⚠️ Switching the serializer requires a full cache flush of all affected cache databases. Existing payloads stay in the previous format and will fail to deserialize on read. Recommended deploy sequence:
text
When auto is the wrong default: an image update that ships
ext-igbinary would silently switch the on-disk format for any cache
that uses auto — and on the next read of an old PHP-serialised
payload, the cache would throw. Pinning the value explicitly ('php'
or 'igbinary') makes the contract observable.
When igbinary is worth it: only for caches storing deeply nested
arrays/objects (e.g. extbase ClassSchema, fluid template reflection).
For string-content caches (rendered pages, large text blobs) or flat
key/value caches (hash, imagesizes) the igbinary encoder overhead
dominates the marginal payload-size win — keep the default. See
CHANGELOG.md for measured numbers.
The session backend (KeyValueSessionBackend) uses JSON internally
for debuggability via valkey-cli — this option has no effect there.
Changelog
See CHANGELOG.md. Notable releases:
- v4.3.0 — Lua-EVAL
set()(1.3×–1.9× faster);serializeropt-in; KeyValueLockingStrategy audit (configurablemaxAcquireAttempts, lazy connect, TTL-cache inwait(), log-level differentiation) - v4.2.0 — TYPO3 Core override pack (
flush,flushByTag,collectGarbage); critical fix forgetAll()SCAN cursor - v4.1.0 — Lazy-connect, MGET-based
getAll(), atomicrenew(), decorrelated-jitter backoff - v4.0.0 — PHP 8.5 baseline, TYPO3 14-only, phpredis 6.3 required
License
GPL-2.0-or-later — see LICENSE for details.