laravel / framework

The Laravel Framework.
https://laravel.com
MIT License
32.47k stars 11.01k forks source link

artisan cache:clear wipes all of Redis #10288

Closed scottconnerly closed 9 years ago

scottconnerly commented 9 years ago

Using Redis for both cache and session, when one calls cache:clear, it flushes the whole store: $this->cache->store($storeName)->flush();

Indeed, in Cache\RedisStore, flush() clears the whole connection's contents: $this->connection()->flushdb();

Could either the session or cache (or both) Redis keys be prefixed with what they are such that clearing one doesn't clear both?

GrahamCampbell commented 9 years ago

This is intended.

GrahamCampbell commented 9 years ago

You need to use a separate redis database if you want to avoid this.

GrahamCampbell commented 9 years ago

By default redis gives you 16 databases, 0->15, and laravel uses db 0 by default.

Gummibeer commented 9 years ago

The same problem occurs with memcached - it flushes the whole server and not just the entries for the executing application. It's dangerous if there are multiple applications that uses the same memcached server for session - if one application runs cache:clear all users in all applications will get logedout.

Would be better if there will be cache:clear & cache:flush or anything like this and an option in the cache config to disable the flush.

Gummibeer commented 9 years ago

example:

public function clear()
{
    $keys = $this->memcached->getAllKeys();
    foreach ($keys as $key) {
        if (Str::startsWith($key, $this->prefix)) {
            $this->memcached->delete($key);
        }
    }
}
GrahamCampbell commented 9 years ago

@Gummibeer It's not a "problem". It's the correct behaviour. If you don't want that, you MUST setup a different database for cache and sessions.

GrahamCampbell commented 9 years ago

By default, redis gives you 16 separate databases, but laravel out of the box will try to use database 0 for both sessions and cache.

Gummibeer commented 9 years ago

It's, like I said, not just a redis thing. It's the same on memcached and I think on all others also. It couldn't be the goal to have a single memcached server for every application!? We solved it yet by creating a custom cache driver and rewrite the flush method - but on production environments it's rly dangerous to flush the whole memcached, redis or what ever you choose as the cache driver.

GrahamCampbell commented 9 years ago

It couldn't be the goal to have a single memcached server for every application!?

You absolutely can do that, BUT you must setup a physically separate database for each application.

GrahamCampbell commented 9 years ago

but on production environments it's rly dangerous to flush the whole memcached, redis

No it's not. If you're reusing the database in other apps, then frankly, you've messed up. That would be like using the same database for all your apps and hoping the tables don't end up with the same name.

summerblue commented 8 years ago

Solution: https://phphub.org/topics/2466

willsmanley commented 4 years ago

For anyone else visiting, I like to set up a minimum of 3 different databases: 0 is the default for things I like to cache manually (like foreign exchange rates every 10 minutes). 1 is for the application cache. 2 is for login sessions.

In config/database.php:

         'default' => [
            'host' => env('REDIS_HOST', localhost),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', 6379),
            'database' => env('REDIS_DB', 0),
        ],

        'cache' => [
            'host' => env('REDIS_HOST', localhost),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', 6379),
            'database' => env('REDIS_CACHE_DB', 1),
        ],

        'session' => [
            'host' => env('REDIS_HOST', localhost),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', 6379),
            'database' => env('REDIS_SESSION_DB', 2),
        ],
Gummibeer commented 4 years ago

@willsmanley I usually add one for the queue and one for the horizon snapshots.

Scyllaly commented 4 years ago

For anyone else visiting, I like to set up a minimum of 3 different databases: 0 is the default for things I like to cache manually (like foreign exchange rates every 10 minutes). 1 is for the application cache. 2 is for login sessions.

In config/database.php:

         'default' => [
            'host' => env('REDIS_HOST', localhost),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', 6379),
            'database' => env('REDIS_DB', 0),
        ],

        'cache' => [
            'host' => env('REDIS_HOST', localhost),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', 6379),
            'database' => env('REDIS_CACHE_DB', 1),
        ],

        'session' => [
            'host' => env('REDIS_HOST', localhost),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', 6379),
            'database' => env('REDIS_SESSION_DB', 2),
        ],

Hi, i have a new questions, now i want to kick off all users by master account, how can i do for clear redis db 2 (like your examples, session => redis db 2)

ahthomsen commented 3 years ago

This might be helpful to others.

I used the config suggested by Scyllaly, but was still flushing the session when running php aritsan cache:clear

The issue for me was that I had left 'connection => 'cache' in the config above the list of connections. Thus, I ended up with the config below which now works:

` 'redis' => [

        'cluster' => false,
        'client' => 'predis',
        'driver' => 'redis',

        'default' => [
            'host' => env('REDIS_HOST', '127.0.0.1'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', 6379),
            'database' => env('REDIS_DB', 0),
        ],

        'cache' => [
            'host' => env('REDIS_HOST', '127.0.0.1'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', 6379),
            'database' => env('REDIS_CACHE_DB', 1),
        ],

        'session' => [
            'host' => env('REDIS_HOST', '127.0.0.1'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', 6379),
            'database' => env('REDIS_CACHE_DB_TWO', 2),
        ],

    ],`