(1/1)聽ErrorException RedisCluster::flushdb() expects exactly 1 parameter, 0 given
IlluminateCacheRedisStore::flush does not accept any parameters and will not pass anything in the call to $this->connection()->flushdb
Set cache driver to redis, set it to use a cluster, call Cache::flush(0 /* or whatever, won't be passed anyway */);
@alibo, do you have any idea how to solve this?
@Dadibom @themsaid PhpRedis, unlike Predis, needs a key to execute this command:
In the case of all commands which need to be directed at a node, the calling convention is identical to the Redis call, except that they require an additional (first) argument in order to deliver the command. Following is a list of each of these commands:
- SAVE
- BGSAVE
- FLUSHDB
- FLUSHALL
- DBSIZE
- BGREWRITEAOF
- LASTSAVE
- INFO
- CLIENT
- CLUSTER
- CONFIG
- PUBSUB
- SLOWLOG
- RANDOMKEY
- PING
https://github.com/phpredis/phpredis/blob/develop/cluster.markdown#directed-node-commands
public function testDBSize() {
for ($i = 0; $i < 10; $i++) {
$str_key = "key:$i";
$this->assertTrue($this->redis->flushdb($str_key));
$this->redis->set($str_key, "val:$i");
$this->assertEquals(1, $this->redis->dbsize($str_key));
}
}
https://github.com/phpredis/phpredis/blob/master/tests/RedisClusterTest.php#L113
If you connect to one of master nodes and run flushdb
command, only data stored in that node will be removed and the rest of the data in other master nodes will remain.
In addition, if you use Predis
, it throws an exception:
>>> Cache::store('redis')->flush();
Predis\NotSupportedException with message 'Cannot use 'FLUSHDB' with redis-cluster.'
As it doesn't remove the whole data stored in all master nodes and Predis doesn't support it, I think we can throw an exception for Cache::flush()
and PhpRedisClusterConnection::flushdb($key = null)
if the client is Redis Cluster.
Also, another option is listing all master nodes and executing flushdb
command on all of them which I don't recommend! :D
@alibo any idea how to list all the masters and run flushdb
on each? Would it work for both phpredis and predis?
@themsaid
For predis
:
$flushDbCommand = new \Predis\Command\ServerFlushDatabase();
foreach ($this->connection()->getConnection() as $node) {
$node->executeCommand($flushDbCommand);
}
more info: https://github.com/nrk/predis/issues/354
For phpredis
:
foreach ($this->connection()->_masters() as [$host, $port]) {
$redis = new Redis();
$redis->connect($host, $port);
$redis->flushDb();
}
more info: https://github.com/phpredis/phpredis/blob/develop/cluster.markdown#directed-node-commands
@themsaid: I still think that "flushdb" is quite dangerous to clear the cache. Especially since Redis cluster has only one database. If you also use Redis for queues or sessions than "cache:clear" will delete those.
I'm not sure what the right solution is. A cache key prefix, cache tags, or something similar.
that's the intended behaviour of flushdb, there is no difference in the risk between cluster and single node setups.
Intended behaviour or not, it's bad UX and can lead to data loss.
Listen mate my point is that you don't know what developers use their caches for. A lot of people use their cache servers as pure caches, in which case a full clear can be done without losing anything important (since it's just cache). And on top of that - this function is in the docs and work with single node redis instances, not having it work on clusters to protect the developers doesn't really make sense
There's a cache prefix by default, right? How about scanning for all keys that start with the cache prefix and deleting those?
Any news on that? Any workaround or advice? We use an automated script to deploy and clear the cache, but this issue complicates things quite a lot... Thanks
This bug doesn't exist anymore.
Which version has the fix?
Scan Or Del is a command for a single redis node.If you do want to use it in the cluster, first get nodes list in the cluster, and run a scan or del for each node.
Read this article for more info [https://qiita.com/mangano-ito/items/92e8a6b434c4b79b790c]
For laravel, to get each connection or node you can use
Redis::client()->getClientFor("127.0.0.1:6379");
then you can delete or scan in each connection.
Most helpful comment
Any news on that? Any workaround or advice? We use an automated script to deploy and clear the cache, but this issue complicates things quite a lot... Thanks