In my situation, I face a problem with redis, our redis service(RDS) is unstable with unknown problem, but I need to solve consistency service and zero-downtime, so on my first solve problem that I do switch service in my application.
Here is my thinking steps:
- Redis service needs to bind container by singlton
- Trying to connect Master redis, if it’s failed, rebinding second redis service.
- No middleware for now, it should be in service provider.
//database.php
'redis' => [
'client' => 'predis',
'default' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => 0,
],
],
'redis_backup' => [
'client' => 'predis',
'default' => [
'host' => env('REDIS_BACKUP_HOST', '127.0.0.1'),
'password' => env('REDIS_BACKUP_PASSWORD', null),
'port' => env('REDIS_BACKUP_PORT', 6379),
'database' => 0,
],
],
As we know, redis service provider by default is defered, so we need to put trying connection and rebinding in boot method.
<?php
namespace App\Providers;
use Illuminate\Redis\RedisManager;
use Illuminate\Support\Arr;
use Illuminate\Support\ServiceProvider;
use Throwable;
class BackupRedisServiceProvider extends ServiceProvider
{
public function boot()
{
try {
// ping redis service.
$this->app['redis']->get(1);
} catch (Throwable $e) {
// we don't care what exceptions, just use backup redis keeping the connection and operations.
// enabled backup redis.
$this->app->singleton('redis', function ($app) {
$config = $app->make('config')->get('database.redis_backup');
return new RedisManager(Arr::pull($config, 'client', 'predis'), $config);
});
$this->app->bind('redis.connection', function ($app) {
return $app['redis']->connection();
});
}
}
}
}
I thought it’s a attempt solution for me, but as you know, we need to solve service unstable and exceptions, this is a other story.