Invalidation
As mentioned in the introduction and events documentation, Relay will invalidate its in-memory cache in real-time. There is an average delay of 100μs
/ 0.1ms
for Redis to inform Relay about invalidations, plus whatever the network latency is.
Even tho it is is strongly discouraged, some rare users may want to disable Relay’s invalidations using the OPT_CLIENT_INVALIDATIONS
option.
Multitenancy limitations
Redis’ invalidation system is not designed for use with multiple databases and will cause unnecessary flushing of Relay’s memory when more than one database is used.
To bypass most of these limitations, it is vital to set a unique prefix for each database connection. We suggest using the format db0:
, db1:
and so on.
$relay->setOption(Relay::OPT_PREFIX, 'db4:');
Unfortunately, due to Redis’ design, Relay isn’t aware of the database index when FLUSHDB
is called and will flush it’s entire memory. If you’re curious, read about the technical details.
Invalidation listeners
In some cases you may wish to listen for the aforementioned invalidation events, however because of PHP’s synchronous nature, when using event listeners the application must request Relay to dispatch registered event listeners.
This is done by calling dispatchEvents()
before cache any operation, as well as automated using native PHP ticks or asynchronous libraries.
Calling dispatchEvents()
Dispatching invalidations is extremely fast and memory efficient, but calling dispatchEvents()
before each cache operation can be a hassle.
$relay->dispatchEvents();
$relay->get('users:count');
Therefore it’s recommended to encapsulate your cache implementation.
use Relay\{Relay, Event};
class Cache extends Psr\Cache\CacheItemPoolInterface
{
public function __construct()
{
$this->relay = new Relay(host: '127.0.0.1', port: 6379);
$this->relay->listen(fn (Event $event) => match ($event->type) {
$event::Flushed => $this->clear(),
$event::Invalidated => $this->deleteItem($event->key),
});
}
public function getItem($key)
{
$this->relay->dispatchEvents();
return $this->relay->get($key);
}
public function hasItem($key) {
$this->relay->dispatchEvents();
return $this->relay->exists($key);
}
/**
* @see https://github.com/cachewerk/relay/tree/main/src/Psr/SimpleCache
*/
}
Using ticks
Ticks are an underused and powerful feature of PHP.
Using ticks to dispatch invalidation is convenient, however the tick count is a delicate balance between performance and reliability.
When ticks are declared for a file, Relay will automatically call registered event listeners every N
ticks.
<?php
declare(ticks = 10);
$relay = new Relay(host: '127.0.0.1', port: 6379);
$relay->listen(function (Relay\Event $event) {
echo "Callback for {$event->type}:{$obj_event->key}\n";
});
while (true) {
$key = 'ticks:' . mt_rand(1, 10);
$relay->set($key, $key);
echo "Set `{$key}`\n";
$relay->get($key);
usleep(100000);
}
Event loops
Use the event loop of any asynchronous library such as ReactPHP, Swoole or Amp
to call dispatchEvents()
.