Redis#
kinetis/cache-redis binds Psr\SimpleCache\CacheInterface to Redis
from REDIS_* configuration, which is how a Kinetis application normally
uses Redis. The kinetis/redis transport underneath it also serves
Queue (Redis) and the Redis session store. Appendix: Redis
holds the full transport and cache contract.
This cache is a runtime key-value store, unrelated to Caching & AOT Compilation’s build-time compilation beyond the shared word.
A cache in a Kinetis application#
composer require kinetis/cache-redis
REDIS_HOST=cache.internal
REDIS_PORT=6379
REDIS_PASSWORD=secret
With Redis configured, AppScope::boot() binds CacheInterface to
Kinetis\SimpleCache\RedisSimpleCache, and any class injects it:
use Psr\SimpleCache\CacheInterface;
final readonly class ArticleSummaries
{
public function __construct(private CacheInterface $cache) {}
/** @param callable(int): array<string, mixed> $load */
public function get(int $id, callable $load): array
{
$key = "article.summary.{$id}";
$summary = $this->cache->get($key);
if ($summary === null) {
$summary = $load($id);
$this->cache->set($key, $summary, 300);
}
return $summary;
}
}
Configuration.
REDIS_URL(redis://:password@host:6379/0) wins outright overREDIS_HOST,REDIS_PORT,REDIS_PASSWORDandREDIS_DATABASE.REDIS_TIMEOUT(default 5 seconds) is the budget for a whole operation, connecting and cluster redirects included, not a connect timeout. Configuration lists every key.Without Redis. With none of
REDIS_URL,REDIS_HOSTandREDIS_CLUSTERset,CacheInterfaceisNullSimpleCache, which always misses and never stores.RateLimitMiddleware(see Middleware) andkinetis/auth-jwt’sRevocationStore(see JWT Authentication) refuse it at construction, since a cache that stores nothing enforces nothing.Redis configured, package missing. The binding is a cache whose every operation throws
SimpleCacheUnavailableExceptionnamingkinetis/cache-redis. The application still boots, so a leftoverREDIS_*key is not fatal, and code that uses the cache fails loudly instead of silently missing.Values and keys. Any serializable PHP value can be stored. Each key is stored as
kinetis_cache:<namespace>:<key>, where the namespace isREDIS_CACHE_NAMESPACE(letters, digits, underscores and dashes;defaultunless set). A failure names the operation, never the key, so a key holding a session identifier or token hash stays out of logs and error pages. A value the serializer cannot encode, and a stored value it cannot decode, are failures like any other: they raiseCacheExceptionrather than returning a miss or the default, andget()leaves the entry where it is.Several keys. Prefer
getMultiple()anddeleteMultiple()to a loop of single calls (Batched reads and deletes).clear()deletes this namespace’s keys and nothing else, by scanning every node’s keyspace. It is neither atomic nor a snapshot: use it to reset a cache, not inside request handling.
Warning
A failed cache call throws Kinetis\SimpleCache\Exception\CacheException.
When its previous exception is Kinetis\Redis\Exception\OutcomeUnknown,
the command was sent and no reply came back, so a set() or delete()
may have been applied. The command is never sent again; repeat it only
when applying it twice is harmless.
A cache on named REDIS_* keys instead of the default ones is
A named cache connection.
The cache AppScope::boot() binds closes its connection when the
application scope is disposed. A cache the application builds and binds
itself registers $app->onDispose($cache->dispose(...)); see
Who closes the connection.
TLS#
Add REDIS_TLS=true to a single-node or cluster connection:
REDIS_HOST=cache.example.com
REDIS_PORT=6380
REDIS_TLS=true
REDIS_TLS_CA_FILE=/etc/ssl/certs/redis-ca.crt
REDIS_TLS_CA_FILE points at a CA certificate to verify the server
against; omit it to use the system’s default trust store.
REDIS_TLS_VERIFY_PEER=false skips verification entirely — useful
against a self-signed certificate in development, not in production.
Redis Cluster#
Set REDIS_CLUSTER=true and REDIS_CLUSTER_SEEDS instead of
REDIS_HOST or REDIS_URL:
REDIS_CLUSTER=true
REDIS_CLUSTER_SEEDS=10.0.0.1:6379,10.0.0.2:6379,10.0.0.3:6379
REDIS_PASSWORD=secret
Several seeds let the client discover the cluster’s layout while one
seed is down. Every key is routed to the node that owns it, and
REDIS_PASSWORD and REDIS_TLS apply to every node. Redis Cluster
serves database 0 only, so there is no REDIS_DATABASE.
kinetis/queue-redis supports standalone Redis only, so it rejects its
connection’s REDIS_CLUSTER=true (see Queue (Redis)).
A seed is host:port, or [address]:port for an IPv6 node:
REDIS_CLUSTER_SEEDS=[2001:db8::10]:6379,[2001:db8::11]:6379
An unbracketed IPv6 address (2001:db8::10:6379) is rejected rather than
guessed at, since its own colons make the port ambiguous. A malformed
seed, an empty entry, or a port outside 1-65535 fails when the cache is
configured, before any connection is attempted. Application code works
against CacheInterface either way.
Warning
A cluster announces its nodes, in CLUSTER SLOTS and in MOVED/ASK
redirects, by IP address unless it is configured with
cluster-announce-hostname and cluster-preferred-endpoint-type hostname. With peer verification on, a certificate carrying only
hostname SANs verifies against the seed and fails against every
discovered node. Give the certificates IP SANs or announce hostnames on
the server; verification is never relaxed for a discovered node.
Raw Redis commands#
CacheInterface covers caching. For any other command, bind a
kinetis/redis client yourself: Using the transport directly shows the
wiring and what each failure means, and the
kinetis/redis README
covers standalone use.
See also#
Appendix: Redis — the transport, its failure and budget contract, cluster routing, and the cache’s commands.
Queue (Redis) — the queue over the same transport.
Configuration — every
REDIS_*key and the named-connection convention.Telemetry — a span per cache operation.