New in version 3.9.0.
coredis allows using a client side cache to eliminate readonly requests to the redis server when a response is available in the local cache.
If enabled the clients will cache the responses for readonly commands by
key/command/arguments. The coredis clients accept any cache
AbstractCache interface and will:
Cache responses for readonly commands acting on single keys (the docstring for the method will indicate whether it supports caching, for example
Return cached responses when they are found if the cache is returning healthy via the
Invalidate the entire cache for a key if a non readonly command is called
If the cache implements
SupportsSamplingand returns a
confidencevalue lower than
100the client will distrust the cached response
(100-$confidence)%of the time and validate the cached response against the actual response from the server. The result of the comparison will be provided to the cache through a call to
feedback()and it is up to the cache implementation to decide what to do with this feedback.
coredis currently ships with an implementation of Server assisted client side caching
that can be used with both the standalone
Redis client or the
client. This implementation enables client tracking for the client so that the redis server
remembers which keys the client has requested and if the key is modified (whether mutated, deleted or expired)
sends a notification that the cache subscribes to to invalidate the cache.
For convenience a proxy class that automatically picks the right implementation based on the
client is available as
from coredis.cache import TrackingCache
cached_client = coredis.Redis(cache=TrackingCache())
regular_client = coredis.Redis()
# or in cluster mode
# cached_client = coredis.RedisCluster("localhost", 7000, cache=InvalidatingCache())
# regular_client = coredis.RedisCluster("localhost", 7000)
async def test():
assert not await cached_client.get("fubar") # None response cached
await regular_client.set("fubar", "bar") # <- triggers a push message to cached_client
assert b"bar" == await cached_client.get("fubar") # Cache should be invalidated
assert b"bar" == await cached_client.get("fubar") # Fetched from local cache
await cached_client.delete(["fubar"]) # Invalidates local cache immediately
assert not await cached_client.get("fubar")
TrackingCache exposes a few configuration options to fine tune
the cache. Specifically the following constructor arguments might be of interest:
Maximum size in bytes that the cache should be allowed to grow to. The cache will periodically shrink the cache in an LRU manner until it is below the threshold.
Maximum number of redis keys to track. This does not map directly to the number of cached entries as the cache maintains a per key, per command, per argument cache.
Maximum time to tolerate no repsonse from the server. The cache instance will use the
PINGcommand to verify if the server is responsive even if no invalidation notifications have been received and if the threshold is breached the in memory cache will be reset and the cache marked unhealthy.
Confidence % in the cache. The client will sample cached values based on the confidence and if the cached value is not the same as the actual response from the server the actual value will be returned and the tainted key invalidated.
If set to
Truethe cache will adjust it’s confidence based on sampled (sampling depends on the initial confidence value itself) validations.