New in Symfony 4.2: Cache stampede protection
November 15, 2018 • Published by Javier Eguiluz
Warning: This post is about an unsupported Symfony version. Some of this information may be out of date. Read the most recent Symfony Docs.
A cache stampede is a type of cascading failure that can occur when systems come under very high load. Consider a web application that caches some page to improve performance. When the cached version of that page expires and the server is under very heavy load, multiple users may be requiring the same uncached page, which could lead to the collapse of the system via exhausting shared resources.
There are multiple techniques to protect against "cache stampede". In Symfony 4.2 we added one called probabilistic early expiration, to the Cache component (we also added a lock-based one for when the cache is cold.)
This technique solves the stampede problem forcing the regeneration of the cached values before they expire. Whenever a value is read from the cache, the application makes a "probabilistic decision" to decide whether the value must be regenerated or not. Thanks to the formula used, the sooner the expiration of the cached value, the higher the probability of recomputing it.
In order to give better control of this "probabilistic decision", the get()
method of CacheInterface
has added a third optional argument called
beta
. It's a float
value that defaults to 1.0
, which provides
optimal stampede protection.
Most of the times you don't have to care about this parameter. Symfony provides
the right default value to protect your apps. However, you can set it to an
arbitrary value or to 0
to disable this protection or to INF
to force an
immediate expiration of the cached value:
1 2 3 4 5 6 7 8
// this closure will be called when a cache key is missing from the backend
$callback = function () { ... return $computedValue; };
// when undefined, beta = 1.0
$productsCount = $cache->get('stats.products_count', $callback);
// beta = INF to force the immediate expiration of this cached value
$productsCount = $cache->get('stats.products_count', $callback, INF);
Help the Symfony project!
As with any Open-Source project, contributing code or documentation is the most common way to help, but we also have a wide range of sponsoring opportunities.
Comments are closed.
To ensure that comments stay relevant, they are closed for old posts.