-
-
Notifications
You must be signed in to change notification settings - Fork 2k
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
[NFR]: Use mGet method when fetching multiple keys from Redis #16689
Comments
@RayHughes I am not sure if this change will be faster. I checked this out last night and yes protected function doGetMultiple(
iterable $keys,
mixed $default = null
): iterable {
$this->fireManagerEvent('cache:beforeGetMultiple', $keys);
$adapterClass = get_class($this->adapter);
if ($adapterClass === Redis::class) {
$results = $this->adapter->getAdapter()->mget($keys);
$results = array_combine($keys, $results);
} else {
$results = [];
foreach ($keys as $element) {
$results[$element] = $this->get($element, $default);
}
}
$this->fireManagerEvent('cache:afterGetMultiple', $keys);
return $results;
} This has introduces problems though. For keys that do not exist, protected function doGetMultiple(
iterable $keys,
mixed $default = null
): iterable {
$this->fireManagerEvent('cache:beforeGetMultiple', $keys);
$adapterClass = get_class($this->adapter);
if ($adapterClass === Redis::class) {
$results = $this->adapter->getAdapter()->mget($keys);
$results = array_map(
function ($element) use ($default) {
return false === $element ? $default : $element;
},
$results
);
$results = array_combine($keys, $results);
} else {
$results = [];
foreach ($keys as $element) {
$results[$element] = $this->get($element, $default);
}
}
$this->fireManagerEvent('cache:afterGetMultiple', $keys);
return $results;
} But now the results come back OK only if I set the serializer to
I guess we can incorporate the unserlialization in the same The resulting code becomes: protected function doGetMultiple(
iterable $keys,
mixed $default = null
): iterable {
$this->fireManagerEvent('cache:beforeGetMultiple', $keys);
$adapterClass = get_class($this->adapter);
if ($adapterClass === Redis::class) {
$results = $this->adapter->getAdapter()->mget($keys);
$serializer = $this->adapter->getSerializer();
$results = array_map(
function ($element) use ($serializer, $default) {
$serializer->unserialize($element);
return false === $element
? $default
: $serializer->getData()
;
},
$results
);
$results = array_combine($keys, $results);
} else {
$results = [];
foreach ($keys as $element) {
$results[$element] = $this->get($element, $default);
}
}
$this->fireManagerEvent('cache:afterGetMultiple', $keys);
return $results;
} I really don't like putting IF statements in the code based on a specific class instead of delegating this to the respective class. If this is the way forward I would have to figure something out so that this is only for Redis and the Cache class stays the same. Thoughts? |
As a quick solution for now, you can use $cache->getAdapter()->getAdapter()->mget($keys) |
I was expecting functionality to work similar to the phpredis method. Your response does make sense, especially since the vast majority of people are using redis with Phalcon are probably using a serializer and using it to store db cache etc. We wound up using hashes for what we needed to accomplish anyway, but figured id open a NFR regardless. |
What about updating mGet to use pipelines instead? So everything is in the same request to the driver. It should save the issue you described above. |
It will be the same really since we will need to have that I am going to change the storage classes to expose I am not sure which one is fastest, Also I want to create some sort of a storage adapter for Redis to take advantage of hashes. It is a bit tricky though because you can store a bunch of data in each hash - I will have to research that |
This has been fixed in #16706 |
Is your feature request related to a problem? Please describe.
The current implementation of
getMultiple
on Phalcon's Redis Cache Adapter is using a loop to fetch keys individually. This makes multiple requests to the Redis server and decreases application performance by increasing latency to the Redis Server.https://github.com/phalcon/phalcon/blob/86e136b75c022b6f86c394b0bd4a0d4a76cccab8/src/Cache/AbstractCache.php#L181
cphalcon/phalcon/Cache/AbstractCache.zep
Line 202 in 83677f1
Describe the solution you'd like
Remove the loop logic for
getMultiple
and use PhpRedis'smGet
method.https://github.com/phpredis/phpredis?tab=readme-ov-file#mget
Describe alternatives you've considered
N/A
Additional context
We store realtime pricing data in Redis with a sub 3 second TTL as the data is updated very frequently. To reduce complexity, the dataset is stored using distributed keys based on category / market. A simple request can fetch upwards of 200 individual items from Redis.
Using Phalcon implementation, reading is delayed by increased latency. Using PhpRedis
mGet
performance is comparable to a single fetch.The text was updated successfully, but these errors were encountered: