-
-
Notifications
You must be signed in to change notification settings - Fork 189
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FEATURE: Optimised Redis cache backend #2721
Conversation
Look neat! Thank you, does this superseed the sandstorm opt or does that still have any extras then? |
@kitsunet thanks. I only added the main new method in this PR, it doesn't cover all the other improvements they did. But the script is already based on the Sandstorm version of the single tag flush. I had a call yesterday with @skurfuerst and we also discussed to now bring over all improvements from the Sandstorm version. I have a few more calls planned with people who modified the Redis backend to get their input too. I would then put all those into a separate PR where everyone with improvements then can chime in. |
With this change the `flushByTags` is optimised to run in batches. The maximum batch size can and should be configured based on the used data source. This change relies on the interface changes in neos#2718
WIth this change optimisations from the community package sandstorm/optimized-redis-backend are introduced into the core Redis backend.
4c03485
to
f9dd34f
Compare
@kitsunet I now added in another commit the remaining optimisations from the sandstorm package. If the change should be "clean" I would need to make the Wdyt? Should I make a "clean" PR and then another for the other optimisations? If we go this way, I would of course adjust the PR title and description. |
flushByTags
for the Redis cache backend
I remember faintly there were issues with that implementation when not used in a "strictly Neos" context, as it had cut some corners to optimize. Not sure if those are still existing, I'll try to research a bit more later today. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I think the only potential issue with the OptimizedRedisCacheBackend
left is the documented behaviour around leaving stale tags in place and the effect that could have on findIdentifiersBytag()
. So if that is "copied"
Another thing I noticed: In the README of OptimizedRedisCacheBackend
it says
For implementing flush(), we just iterate over the relevant part of the keyspace and remove all elements. Before, this was done through a similar logic as explained in FlushByTag, because the Redis Backend was freezable (but we do not need this for Neos Content Cache).
So, if this is case, implementing FreezableBackendInterface
should be removed from the backend, no?
Trigger checks |
I will test the difference related to performance when keeping this part.
But the backend is not only for Neos? So I would leave it in there. Shouldn't hurt to keep it. Doesn't look like I should have a big impact. But will test. What do you think about increasing the minimum Redis version to the 6.0.0 which is the oldest with EOL? |
I fixed the Psalm complaint, but the test failures look legit… |
That's my point - if it's kept, it should behave like before, but I understand the README says it differs… So either remove freezability or keep behaviour.
Fine with me… |
Will check |
All Redis versions < 6.0.0 are already EOL. This would allow us to improve the backends behaviour by using more recent features of Redis.
This prevents getting non existent identifiers when calling `findIdentifiersByTag`.
Due to the removal of the `entries` cache entry to track all entries, the iteration must now be done by retrieving all matching keys from the cache.
Ok a unit test fails now, will check again... |
Everything green, hope I didn't miss anything. But at least I now know 1000% more about Redis than before 😎 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two more tiny suggestions… and the class docblock still says:
* Since Redis < 2.8.0 does not provide a mechanism for iterating over keys,
* a separate list with all entries is populated
That is not true anymore?! At least the version mentioned is no longer supported, so is there a better way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Notwithstanding my tiny remarks, this seems to work just fine… I only did limited testing (compared to what @Sebobo did), but… ✅
You are right, that was my last change to clean that up after I had read it, but forgot to remove the text. |
efa53e7
to
6ad44bc
Compare
After the updated docblocks i get "Typed property Neos\Cache\Backend\RedisBackend::$frozen must not be accessed before initialization" Does this rely on features from #2701 |
Co-authored-by: Marc Henry Schultz <85400359+mhsdesign@users.noreply.github.com>
* @var integer Cursor used for iterating over cache entries | ||
*/ | ||
protected $entryCursor = 0; | ||
protected ?bool $frozen = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
protected ?bool $frozen = null; | |
protected bool $frozen = false; |
since the getter declares its return type as bool that would conflict anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume it was done like that because when it's null
the getter retrieves the value from Redis and "caches" it this way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't know much about redis and I can't process the lua scripts in a way to decide if they are sane or not. So I just left three suggestions to use union false
pseudo type instead of the more generic bool
: https://www.php.net/manual/de/language.types.declarations.php#language.types.declarations.composite.union.false
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function key() | ||
public function key(): string|bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public function key(): string|bool | |
public function key(): string|false |
* @api | ||
*/ | ||
public function get(string $entryIdentifier) | ||
public function get(string $entryIdentifier): string|bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public function get(string $entryIdentifier): string|bool | |
public function get(string $entryIdentifier): string|false |
@@ -310,28 +355,30 @@ public function findIdentifiersByTag(string $tag): array | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function current() | |||
public function current(): string|bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public function current(): string|bool | |
public function current(): string|false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me and works on my machine. Am no redis expert
awesome work everybody ❤️ ❤️ ❤️ I'll add docs to OptimizedRedisCacheBackend, marking it as obsolete starting with Neos 8.0 💯 |
redis.call('DEL', key) | ||
end | ||
"; | ||
$this->redis->eval($script, [$this->getPrefixedIdentifier('frozen'), $this->getPrefixedIdentifier('')], 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$this->getPrefixedIdentifier('frozen')
is not needed anymore, is it? At least KEYS[1] is never accessed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is still needed, but properly the script is incorrect now. Will check and adjust the test. Thx for noticing!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, you are right, the key is already included in the args with wildcard.
Hi @skurfuerst, thx. There is still a difference to your package as I enabled the removal of related tags again, which you didn't do in the "optimised" version. There might still be a need for a |
Hm.
The 7.3.8 version was tagged on the 8.2 branch AFAICT. |
And 7.3.7 was tagged in HEAD off of 7.3 and later merged back into 7.3 (which is confusing, but correct.) |
What I did
With this change the
flushByTags
is optimised to run flush operations in batches.The maximum batch size can and should be configured based on the used data source.
This change relies on the interface changes in #2718
Additionally all optimisations from https://github.com/sandstorm/OptimizedRedisCacheBackend were added.
How I did it
Instead of uploading the flush Lua script and only flushing the entries for one tag.
The same is now done for batches of tags reducing the calls to Redis and the
evaluation time Redis needs to parse the script.
How to verify it
#2718 includes updated tests for the Redis backend that will also check this method.
Checklist