-
Notifications
You must be signed in to change notification settings - Fork 11.7k
Description
Laravel Version
12.40.2
PHP Version
8.4
Database Driver & Version
No response
Description
I posted on issue #58000.
I had an issue with phpredis
The error message was:
phpredis - Couldn't map cluster keyspace using any provided seed Solved
Based on the Laravel documentation to set up a Redis cluster connection the config should look like:
'redis' => [
'client' => env('REDIS_CLIENT', 'phpredis'),
'options' => [
'cluster' => env('REDIS_CLUSTER', 'redis'),
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
],
'clusters' => [
'default' => [
[
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'username' => env('REDIS_USERNAME'),
'password' => env('REDIS_PASSWORD'),
'port' => env('REDIS_PORT', '6379'),
'database' => env('REDIS_DB', '0'),
],
],
],
// ...
],I had to setup Redis cluster with phpredis with ACL authentication.
The issue I found is when calling method createRedisClusterInstance on PhpRedisConnector class
return tap(new RedisCluster(...$parameters) ...The fifth argument auth on variable $parameters is set as null.
To solve the issue I had to change my configuration
'redis' => [
'client' => env('REDIS_CLIENT', 'phpredis'),
'options' => [
'cluster' => env('REDIS_CLUSTER', 'redis'),
'prefix' => env('REDIS_PREFIX', 'my_prefix:'),
'password' => env('REDIS_USERNAME', null) ? [env('REDIS_USERNAME', null), env('REDIS_PASSWORD', null)] : env('REDIS_PASSWORD', null),
],
'clusters' => [
'default' => [
[
'host' => env('REDIS_HOST_1', '127.0.0.1'),
'username' => env('REDIS_USERNAME', null),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', '6379'),
'database' => env('REDIS_DB', '0'),
'persistent' => true,
],
[
'host' => env('REDIS_HOST_2', '127.0.0.1'),
'username' => env('REDIS_USERNAME', null),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', '6379'),
'database' => env('REDIS_DB', '0'),
'persistent' => true,
],
[
'host' => env('REDIS_HOST_3', '127.0.0.1'),
'username' => env('REDIS_USERNAME', null),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', '6379'),
'database' => env('REDIS_DB', '0'),
'persistent' => true,
],
],
],
],Also as if you noticed 'persistent' => true, should be inside of each cluster connection.
Issue:
The class that generates the mapping for the variable $parameters is not mapping corrected.
OR
Laravel docs should be updated.
Hey @crynobone.
I did upgrade my Laravel framework 12.40.2 and the PHP version 8.4. and the issue still present. I have worked around
What I noticed on this new version is the 5th parameter is not present at all, as the previous version was set to null.
I do believe the method that maps the config into the $parameter is not reading for each cluster node neither from the options username and password.
The solution for me was to add credentials combined as you see below.
'options' => [
'cluster' => env('REDIS_CLUSTER', 'redis'),
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
'password' => env('REDIS_USERNAME', null) ? [env('REDIS_USERNAME', null), env('REDIS_PASSWORD', null)] : env('REDIS_PASSWORD', null),
],Steps To Reproduce
Requires a Redis cluster with ACL
I added a test endpoint, as you see I had to keep the cache as database and change to redis on runtime to be able to test this endpoint.
Route::get('/cache-test', [TestController::class, 'cacheTest']);
class TestController extends Controller
{
public function cacheTest(Request $request): JsonResponse
{
$validated = $request->validate([
'key' => ['required', 'string', 'max:20', 'not_in:key'],
'value' => ['required', 'string', 'max:100'],
'ttl' => ['required', 'integer', 'min:20', 'max:180'],
], [
'key.not_in' => 'The key name "key" is reserved and cannot be used.',
]);
config(['cache.default' => 'redis']);
$client = config('database.redis.client');
$cacheStore = config('cache.default');
$ttl = $validated['ttl'];
$key = $validated['key'];
$value = $validated['value'];
try {
$class = get_class(Redis::connection()->client());
Cache::put($key, $value, $ttl);
$cachedValue = Cache::get($key);
$data = [
'status' => 'success',
'message' => 'Redis cache is working!',
'key_set' => $key,
'value_retrieved' => $cachedValue,
'ttl_seconds' => $ttl,
'store' => $cacheStore,
'client' => $client,
'class' => $class,
];
if ($cachedValue && $cachedValue === $value) {
return response()->json($data);
}
$data['status'] = 'failure';
$data['message'] = 'Cache set but retrieved value does not match.';
return response()->json($data);
} catch (Exception $e) {
return response()->json([
'status' => 'error',
'message' => 'Redis connection failed or another cache error occurred.',
'error_detail' => $e->getMessage(),
], 500);
}
}
}