Node.js应用连接Redis时出现“Socket already opened”与“The client is closed”错误的排查咨询
Hey there, let's break down what's causing your Redis connection issues and fix them step by step!
Why You're Seeing These Errors
- "Socket already opened": You're calling
await client.connect()every time your route runs, but you've exported a single Redis client instance fromredisClient.ts. Once that client connects on the first request, trying to callconnect()again on the same instance throws this error—since the socket is already open. - "The client is closed": If you skip
connect(), the client starts in a closed state by default, so it can't send any commands to Redis.
Fix 1: Connect Once When Initializing the Client
The cleanest approach is to connect your Redis client once when the app starts, not on every request. Update your redisClient.ts like this:
import redis = require('redis'); const client = redis.createClient({url: 'myRedisURL'}); // Handle connection errors to avoid uncaught exceptions client.on('error', (err) => console.error('Redis Client Error:', err)); // Connect immediately when the module loads (async () => { try { await client.connect(); console.log('Successfully connected to Redis'); } catch (err) { console.error('Failed to connect to Redis:', err); } })(); export default client;
Then in myRoute.ts, remove the await client.connect() line entirely—you can use the client directly:
import client from './redisClient'; // ... your route logic let redisValue: string | null; redisValue = await client.get(key); if (!redisValue) { redisValue = await some_external_api_call(key); // Fix: Use redisValue instead of the undefined "value" variable await client.set(key, redisValue, {EX: 3600 * 24}); }
Fix 2: Check Connection State Before Using (For Dynamic Scenarios)
If you need to handle cases where the client might disconnect and reconnect later, add a check for the client's ready state before sending commands:
import client from './redisClient'; // ... your route logic let redisValue: string | null; try { // Only connect if the client isn't already ready if (!client.isReady) { await client.connect(); } redisValue = await client.get(key); if (!redisValue) { redisValue = await some_external_api_call(key); await client.set(key, redisValue, {EX: 3600 * 24}); } } catch (err) { console.error('Redis operation failed:', err); // Add error handling for your route here (e.g., return a 500 response) }
Extra Tips to Avoid Future Issues
- Variable Typo: Your original code uses
valueinclient.set()but definesredisValue—fix that to avoid undefined variable errors. - Single Instance: Always use a single Redis client instance across your app. Creating a new client per request will exhaust your Redis connection pool quickly.
- Graceful Shutdown: Add code to close the Redis connection when your app exits:
process.on('SIGINT', async () => { await client.quit(); process.exit(0); });
内容的提问来源于stack exchange,提问作者Edward Martin
相关产品推荐
相关产品推荐

