Skip to content
Snippets Groups Projects
Commit d9ae0f9f authored by Sascha Grossenbacher's avatar Sascha Grossenbacher
Browse files

Issue #3498940 by berdir: Optimize bin cache tags and last write timetamp

parent c5381204
Branches
Tags
1 merge request!49bypass regular cache for last write timestamps
Pipeline #399678 passed with warnings
......@@ -7,6 +7,7 @@ use Drupal\Component\Assertion\Inspector;
use Drupal\Component\Serialization\SerializationInterface;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Cache\ChainedFastBackend;
use Drupal\Core\Site\Settings;
use Drupal\redis\RedisPrefixTrait;
......@@ -126,10 +127,34 @@ abstract class CacheBase implements CacheBackendInterface {
$this->setPermTtl();
}
/**
* Checks whether the cache id is the last write timestamp.
*
* Cache requests for this are streamlined to bypass the full cache API as
* that needs two extra requests to check for delete or invalidate all flags.
*
* Most requests will only fetch this single timestamp from bins using the
* ChainedFast backend.
*
* @param string $cid
* The requested cache id.
*
* @return bool
*/
protected function isLastWriteTimestamp(string $cid): bool {
return $cid === ChainedFastBackend::LAST_WRITE_TIMESTAMP_PREFIX . 'cache_' . $this->bin;
}
/**
* {@inheritdoc}
*/
public function get($cid, $allow_invalid = FALSE) {
if ($this->isLastWriteTimestamp($cid)) {
$timestamp = $this->client->get($this->getPrefix() . ':' . $cid);
return $timestamp ? (object) ['data' => $timestamp] : NULL;
}
$cids = [$cid];
$cache = $this->getMultiple($cids, $allow_invalid);
return reset($cache);
......@@ -325,6 +350,10 @@ abstract class CacheBase implements CacheBackendInterface {
if ($cache->valid && !$this->checksumProvider->isValid($cache->checksum, $cache->tags)) {
$cache->valid = FALSE;
}
// Remove the bin cache tag to not expose that, otherwise it is reused
// by the fast backend in the FastChained implementation.
$cache->tags = array_diff($cache->tags, [$this->getTagForBin()]);
}
// Ensure the entry does not predate the last delete all time.
......
......@@ -5,6 +5,7 @@ namespace Drupal\redis\Cache;
use Drupal\Component\Serialization\SerializationInterface;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheTagsChecksumInterface;
use Drupal\Core\Cache\ChainedFastBackend;
/**
* PhpRedis cache backend.
......@@ -82,6 +83,11 @@ class PhpRedis extends CacheBase {
*/
public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = []) {
if ($this->isLastWriteTimestamp($cid)) {
$this->client->set($this->getPrefix() . ':' . $cid, $data);
return;
}
$ttl = $this->getExpiration($expire);
$key = $this->getKey($cid);
......
......@@ -2,6 +2,7 @@
namespace Drupal\redis\Cache;
use Drupal\Core\Cache\ChainedFastBackend;
use Predis\Client;
use Drupal\Component\Serialization\SerializationInterface;
use Drupal\Core\Cache\Cache;
......@@ -83,6 +84,11 @@ class Predis extends CacheBase {
*/
public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = []) {
if ($this->isLastWriteTimestamp($cid)) {
$this->client->set($this->getPrefix() . ':' . $cid, $data);
return;
}
$ttl = $this->getExpiration($expire);
$key = $this->getKey($cid);
......
......@@ -6,6 +6,7 @@ use Drupal\Component\Assertion\Inspector;
use Drupal\Component\Serialization\SerializationInterface;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheTagsChecksumInterface;
use Drupal\Core\Cache\ChainedFastBackend;
use Drupal\Core\Site\Settings;
/**
......@@ -97,6 +98,11 @@ class Relay extends CacheBase {
*/
public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = []) {
if ($this->isLastWriteTimestamp($cid)) {
$this->client->Set($this->getPrefix() . ':' . $cid, $data);
return;
}
$ttl = $this->getExpiration($expire);
$key = $this->getKey($cid);
......
<?php
namespace Drupal\Tests\redis\Kernel;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Cache\ChainedFastBackend;
use Drupal\Core\Cache\PhpBackend;
/**
* Tests Redis cache backend using GenericCacheBackendUnitTestBase.
*
* @group redis
*/
class ChainedFastWithRedisCacheTest extends RedisCacheTest {
/**
* Creates a new instance of ChainedFastBackend.
*
* @return \Drupal\Core\Cache\ChainedFastBackend
* A new ChainedFastBackend object.
*/
protected function createCacheBackend($bin) {
$consistent_backend = \Drupal::service('cache.backend.redis')->get($bin);
$consistent_backend->setMinTtl(10);
$fast_backend = new PhpBackend($bin, \Drupal::service('cache_tags.invalidator.checksum'), \Drupal::service(TimeInterface::class));
$backend = new ChainedFastBackend($consistent_backend, $fast_backend, $bin);
// Explicitly register the cache bin as it can not work through the
// cache bin list in the container.
\Drupal::service('cache_tags.invalidator')->addInvalidator($backend);
return $backend;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment