Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Cache] Redis PSR-6 getItem should not use transactions by default #22922

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

Closed
Tasiobg opened this issue May 26, 2017 · 7 comments
Closed

[Cache] Redis PSR-6 getItem should not use transactions by default #22922

Tasiobg opened this issue May 26, 2017 · 7 comments

Comments

@Tasiobg
Copy link

Tasiobg commented May 26, 2017

Q A
Bug report? yes
Feature request? no
BC Break report? no
RFC? no
Symfony version 3.2

File affected https://github.com/symfony/cache/blob/3e22d4ac7a60f7421f1c9e8dd15140f072834480/Traits/RedisTrait.php#L278

Function:
private function pipeline(\Closure $generator)

Redis PSR-6 getItem() operations are run inside the pipeline as a Redis transaction instead of a normal "get" operation, for instance check line 307 ($this->redis->multi). Redis transactions should be slower and they have side effect, in my case I'm running RedisCluster and I set it to distribute the load between the master and slaves but using transactions is running all operation only on the master server.

For instance it could be reproduced by using phpredis module and setting the RedisCluster connection to something like this:

// Create a cluster setting two nodes as seeds
$obj_cluster = new RedisCluster(NULL, Array("host:7000", "host:7001","host:7003"));

// Always distribute readonly commands between masters and slaves, at random
$obj_cluster->setOption(
    RedisCluster::OPT_FAILOVER, RedsiCluster::FAILOVER_DISTRIBUTE
);

I have done a quick fix, I have change the last else condition to no use transactions and in this case works fine, load get distributed.
this is the change I did for the test

else {
    $results[];
    $i = 0;
    foreach ($generator() as $command => $args) {
        $ids[$i] = $args[0];
        $results[$i++] = call_user_func_array(array($this->redis, $command), $args);
    }
}

If for any reason this is not a bug and PSR-6 Redis adapter is mean to wrap single operations into a transaction, would be nice to have an option to disable this behaviour.

@Tasiobg Tasiobg changed the title [Cache] Redis getItem should not use transactions by default [Cache] Redis PSR-6 getItem should not use transactions by default May 26, 2017
@nicolas-grekas
Copy link
Member

AFAIK, pipeline is not transactional. But since it uses one single connection to fetch several items at once, it gets them from the same server. Still, each read should be independent, I don't know why the master is always selected. Could it be a phpredis issue?
To me, the code is correct: if you ask several items at once, fetching them in batch is expected. If you don't, you can call getItem() several times.

@Tasiobg
Copy link
Author

Tasiobg commented May 26, 2017

Looks like phpredis implementation of "multi" may set the server into transaction mode and this mode only run on master, but not sure
https://github.com/phpredis/phpredis#transactions
Maybe I should try to report this on the phpredis github.

@Tasiobg
Copy link
Author

Tasiobg commented May 26, 2017

I have open an issue on phpredis phpredis/phpredis#1186

@nicolas-grekas
Copy link
Member

Thanks. How does a predis client behave?

@nicolas-grekas
Copy link
Member

I got it: since a pipeline can have read and write ops, the master has to be selected...

@nicolas-grekas
Copy link
Member

See #22924

@Tasiobg
Copy link
Author

Tasiobg commented May 27, 2017

Nice one @nicolas-grekas, this should work.

nicolas-grekas added a commit that referenced this issue May 28, 2017
…kas)

This PR was merged into the 3.2 branch.

Discussion
----------

[Cache] Dont use pipelining with RedisCluster

| Q             | A
| ------------- | ---
| Branch?       | 3.é
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #22922
| License       | MIT
| Doc PR        | -

phpredis doesn't support pipelining with RedisCluster
see https://github.com/phpredis/phpredis/blob/develop/cluster.markdown#pipelining
and multiple operations (MSET/MGET) work but only "per-shard".

We have to fetch keys one by one for now at least.

Commits
-------

eb93ac9 [Cache] Dont use pipelining with RedisCluster
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants