diff options
author | Timo Tijhof <krinkle@fastmail.com> | 2023-03-23 12:52:09 -0700 |
---|---|---|
committer | Timo Tijhof <krinkle@fastmail.com> | 2023-04-29 01:23:56 +0100 |
commit | f83f75d3e64e9352c36d10b6280ca0d0b52b38d2 (patch) | |
tree | 7d92d18b982d83abde0850c98a8cc5704b7ec1d4 /includes/libs/objectcache | |
parent | 39fb10aa719f0614713fc5495e95f7151478586b (diff) | |
download | mediawikicore-f83f75d3e64e9352c36d10b6280ca0d0b52b38d2.tar.gz mediawikicore-f83f75d3e64e9352c36d10b6280ca0d0b52b38d2.zip |
objectcache: Remove WANObjectCache's internal cool-off bounce feature
Bug: T203786
Bug: T302623
Bug: T321634
Change-Id: Ie3a2215d3325fe7290658e1013adaac4f4565884
Diffstat (limited to 'includes/libs/objectcache')
-rw-r--r-- | includes/libs/objectcache/wancache/WANObjectCache.php | 83 |
1 files changed, 2 insertions, 81 deletions
diff --git a/includes/libs/objectcache/wancache/WANObjectCache.php b/includes/libs/objectcache/wancache/WANObjectCache.php index f0d77019f6d6..876d6a9ee46e 100644 --- a/includes/libs/objectcache/wancache/WANObjectCache.php +++ b/includes/libs/objectcache/wancache/WANObjectCache.php @@ -224,8 +224,6 @@ class WANObjectCache implements /** Seconds to keep lock keys around */ private const LOCK_TTL = 10; - /** Seconds to no-op key set() calls to avoid large blob I/O stampedes */ - private const COOLOFF_TTL = 2; /** Seconds to ramp up the chance of regeneration due to expected time-till-refresh */ private const RAMPUP_TTL = 30; @@ -302,8 +300,6 @@ class WANObjectCache implements private const TYPE_MUTEX = 'm'; /** Single character component for interium value keys */ private const TYPE_INTERIM = 'i'; - /** Single character component for cool-off bounce keys */ - private const TYPE_COOLOFF = 'c'; /** Value prefix of purge values */ private const PURGE_VAL_PREFIX = 'PURGED'; @@ -1776,10 +1772,9 @@ class WANObjectCache implements // Callback yielded a cacheable value ( $value !== false && $ttl >= 0 ) && // Current thread was not raced out of a regeneration lock or key is tombstoned - ( !$useRegenerationLock || $hasLock || $isKeyTombstoned ) && - // Key does not appear to be undergoing a set() stampede - $this->checkAndSetCooloff( $key, $kClass, $value, $elapsed, $hasLock ) + ( !$useRegenerationLock || $hasLock || $isKeyTombstoned ) ) { + $this->stats->timing( "wanobjectcache.$kClass.regen_set_delay", 1e3 * $elapsed ); // If the key is write-holed then use the (volatile) interim key as an alternative if ( $isKeyTombstoned ) { $this->setInterimValue( @@ -1932,80 +1927,6 @@ class WANObjectCache implements } /** - * Check whether to skip set() on account of concurrent I/O spike rate-limiting - * - * This mitigates problems caused by popular keys suddenly becoming unavailable due to - * unexpected evictions or cache server outages. These cases are not handled by the usual - * preemptive refresh logic. - * - * With a typical scale-out infrastructure, CPU and query load from getWithSetCallback() - * invocations is distributed among appservers and replica DBs, but cache operations for - * a given key route to a single cache server (e.g. striped consistent hashing). A set() - * stampede to a key can saturate the network link to its cache server. The intensity of - * the problem is proportionate to the value size and access rate. The duration of the - * problem is proportionate to value regeneration time. - * - * @param string $key Cache key made with makeKey()/makeGlobalKey() - * @param string $kClass Key collection name - * @param mixed $value The regenerated value - * @param float|null $elapsed Seconds spent fetching, validating, and regenerating the value - * @param bool $hasLock Whether this thread has an exclusive regeneration lock - * @return bool Whether it is OK to proceed with a key set operation - */ - private function checkAndSetCooloff( $key, $kClass, $value, $elapsed, $hasLock ) { - if ( is_scalar( $value ) ) { - // Roughly estimate the size of the value once serialized - $hypotheticalSize = strlen( (string)$value ); - } else { - // Treat the value is a generic sizable object - $hypotheticalSize = $this->keyHighByteSize; - } - - if ( !$hasLock ) { - // Suppose that this cache key is very popular (KEY_HIGH_QPS reads/second). - // After eviction, there will be cache misses until it gets regenerated and saved. - // If the time window when the key is missing lasts less than one second, then the - // number of misses will not reach KEY_HIGH_QPS. This window largely corresponds to - // the key regeneration time. Estimate the count/rate of cache misses, e.g.: - // - 100 QPS, 20ms regeneration => ~2 misses (< 1s) - // - 100 QPS, 100ms regeneration => ~10 misses (< 1s) - // - 100 QPS, 3000ms regeneration => ~300 misses (100/s for 3s) - $missesPerSecForHighQPS = ( min( $elapsed, 1 ) * $this->keyHighQps ); - - // Determine whether there is enough I/O stampede risk to justify throttling set(). - // Estimate unthrottled set() overhead, as bps, from miss count/rate and value size, - // comparing it to the per-key uplink bps limit (KEY_HIGH_UPLINK_BPS), e.g.: - // - 2 misses (< 1s), 10KB value, 1250000 bps limit => 160000 bits (low risk) - // - 2 misses (< 1s), 100KB value, 1250000 bps limit => 1600000 bits (high risk) - // - 10 misses (< 1s), 10KB value, 1250000 bps limit => 800000 bits (low risk) - // - 10 misses (< 1s), 100KB value, 1250000 bps limit => 8000000 bits (high risk) - // - 300 misses (100/s), 1KB value, 1250000 bps limit => 800000 bps (low risk) - // - 300 misses (100/s), 10KB value, 1250000 bps limit => 8000000 bps (high risk) - // - 300 misses (100/s), 100KB value, 1250000 bps limit => 80000000 bps (high risk) - if ( ( $missesPerSecForHighQPS * $hypotheticalSize ) >= $this->keyHighUplinkBps ) { - $cooloffSisterKey = $this->makeSisterKey( $key, self::TYPE_COOLOFF ); - $watchPoint = $this->cache->watchErrors(); - if ( - !$this->cache->add( $cooloffSisterKey, 1, self::COOLOFF_TTL ) && - // Don't treat failures due to I/O errors as the key being in cool-off - $this->cache->getLastError( $watchPoint ) === self::ERR_NONE - ) { - $this->logger->debug( "checkAndSetCooloff($key): bounced; {$elapsed}s" ); - $this->stats->increment( "wanobjectcache.$kClass.cooloff_bounce" ); - - return false; - } - } - } - - // Corresponding metrics for cache writes that actually get sent over the write - $this->stats->timing( "wanobjectcache.$kClass.regen_set_delay", 1e3 * $elapsed ); - $this->stats->updateCount( "wanobjectcache.$kClass.regen_set_bytes", $hypotheticalSize ); - - return true; - } - - /** * @param string $key Cache key made with makeKey()/makeGlobalKey() * @param float $minAsOf Minimum acceptable value "as of" UNIX timestamp * @param float $now Fetch time to determine "age" metadata |