How to clear redis cache while keeping session data : Laravel 5
Asked Answered
L

5

13

I am using redis as a session driver and I want to clear the cache while keeping the session data, so basically user can stay logged in. Any suggestions regarding restructuring or handling the current situation?

Note: I don't want to use separate redis instance for sessions and other cache data.

Laissezfaire answered 31/1, 2016 at 7:30 Comment(0)
N
33

Intro

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.

Our solution is to let Redis caching using database 0, and database 1 for Session, there for solving the session clear by running php artisan cache:clear problem.

1. Setting up Session Redis connection

Modify config/database.php, add session key to the redis option:

'redis' => [

   'cluster' => false,

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

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

2. Make use of the session connection

Modify config/session.php, change the following:

'connection' => null,

to:

'connection' => 'session',

3. Using Redis as session driver

Modify .env, change SESSION_DRIVER:

SESSION_DRIVER=redis

4. Testing out

Execute the following artisan command, then check your login state:

php artisan cache:clear

If the login state persists, voilà!

Narrate answered 30/7, 2016 at 10:52 Comment(1)
This doesn't work if you have cluster (multiple databases are not supported)Spritsail
A
3

I don't know Laravel, but in general the best two options would be:

  1. Change the format of the cache keys. You should use versioned cache keys so you can do it in the future, i.e. "cache.1." so you can increment and then it makes all your keys irrelevant at once.

  2. Move the cache to a different db number in the same redis instance. That way you can also later do FLUSHDB on that db number to clear the cache.

In both options, after you first do it, if the cache keys are not time-expiring, you should create a script that uses SCAN to remove old keys. See http://redis.io/commands/scan

As a side note, it's usually a bad idea to keep cache and other things in the same redis instance, as in caches you usually use LRU based eviction, and you don't want to mix that with less volatile keys.

Archlute answered 31/1, 2016 at 7:50 Comment(0)
D
2

https://laravel.com/docs/5.2/redis#configuration

'redis' => [
    'cluster' => false,
    'default' => [
        'host'     => '127.0.0.1',
        'port'     => 6379,
        'database' => 0,
    ],
],

There is 'database' in redis connection options, just select different databases for session and cache. I just hope that redis cache driver uses flushdb not flushall for flushing :).

Desai answered 1/2, 2016 at 22:45 Comment(2)
Note: I don't want to use separate redis instance for sessions and other cache data.Laissezfaire
You don't need to create different redis instances. One redis instance offers multiple "databases", you just need to point which one you want to use. ( rediscookbook.org/multiple_databases.html )Desai
A
1

For the laravel 9 (it is similar for an older ones):

1.update session configuration

you must put in .env:

SESSION_CONNECTION=session

that configuration is then loaded at config/session.php

'connection' => env('SESSION_CONNECTION'),

That tells laravel to store sessions in separated redis/database connection

2.update redis configuration

add new redis connection at the config/database.php for sessions

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

you can use and database number from 0 to 16. For other connections put different database number.

3.clear cache(without touching sessions)

now you can clear the redis cache with this piece of code:

$redisConnection = \Illuminate\Support\Facades\Redis::connection('default');
$redisConnection->flushDB();

TIP: You can put that code in custom command and run it with the artisan

BONUS: You can see and clear all redis data for each connection with:

$redisSession = \Illuminate\Support\Facades\Redis::connection('session');//session|queue|default
$redisSessionKeys = $redisSession->keys('*');
$redisSession->flushDB();
dd($redisSessionKeys);

BONUS2: You can also add "redis database" for queues and then you have queue jobs, sessions and cache separated and you can clear only one of them

'redis' => [
   ...
   'default' => [
         'host'     => env('REDIS_HOST', 'localhost'),
         'password' => env('REDIS_PASSWORD', null),
         'port'     => env('REDIS_PORT', 6379),
         'database' => 0,
   ],
   'session' => [
         'host'     => env('REDIS_HOST', 'localhost'),
         'password' => env('REDIS_PASSWORD', null),
         'port'     => env('REDIS_PORT', 6379),
         'database' => 1,
   ],
  'queue' => [
         'host'     => env('REDIS_HOST', 'localhost'),
         'password' => env('REDIS_PASSWORD', null),
         'port'     => env('REDIS_PORT', 6379),
         'database' => 2,
   ],
]
Agbogla answered 25/11, 2022 at 12:45 Comment(0)
S
0

Laravel Cache::clear() sends the Redis flushall command which will dump everything so not very useful in my experience. You will need to extend the cache class and create a custom set to index the cache data you want to be able to clear. Then build an another function to read the set and issue Redis del() command for each key in the set. Post some working code and will detail further if necessary

Notagolfers suggestion of separation of cache and session into different redis databases isn't a had call but you will still need to extend the cache class to implement the Redis database config switch

Soviet answered 31/1, 2016 at 9:54 Comment(1)
\vendor\laravel\framework\src\Illuminate\Cache\RedisStore.php's flush method calls $this->connection->flushdb() which ultimately calls Redis' FLUSHDB command. FLUSHDB deletes all the keys for the given connection/database - default is 0 as you can see from the config. FLUSHALL would delete all keys for all databases which would be rather undesirable behavior if you had, for example, segregated cache keys from session keys in different Redis DB's.Quadragesima

© 2022 - 2024 — McMap. All rights reserved.