【help】Nodejs+redis+mysql,redis连接没有正常断掉

【help】Nodejs+redis+mysql,redis连接没有正常断掉

我用nodejs做web应用,逻辑大概是这样:

请求过来,先查redis,查完插入mysql,查完断掉redis和mysql的连接。 我监听了redis的connect事件,一直有事件响应。 我有调用chient.quit,并且打了日志,但是这条日志之后,还会不断地有connect事件的日志打印。

有人出现过这种问题吗?

3 回复

【help】Nodejs+redis+mysql,redis连接没有正常断掉

大家好,我在使用Node.js开发一个Web应用时遇到了一个问题。我的逻辑大致如下:

  1. 当接收到请求时,首先尝试从Redis中获取数据。
  2. 如果Redis中没有数据,则将数据插入到MySQL数据库中。
  3. 每次请求处理完毕后,都会尝试断开Redis和MySQL的连接。

然而,我发现Redis的连接并没有像预期那样被正常关闭。具体来说,我已经监听了Redis的connect事件,并且在代码中明确调用了client.quit()方法来断开连接。奇怪的是,在调用client.quit()之后,仍然不断有connect事件的日志打印出来。

问题描述

  • 问题:Redis连接没有正常断开。
  • 现象:调用client.quit()之后,仍然有Redis的connect事件触发。
  • 代码示例
const redis = require('redis');
const mysql = require('mysql');

// 创建Redis客户端
const client = redis.createClient({
    host: 'localhost',
    port: 6379,
});

// 监听connect事件
client.on('connect', () => {
    console.log('Redis client connected');
});

// 监听error事件
client.on('error', (err) => {
    console.error(`Error ${err}`);
});

// 请求处理函数
async function handleRequest(req, res) {
    try {
        // 尝试从Redis中获取数据
        const data = await new Promise((resolve, reject) => {
            client.get('key', (err, reply) => {
                if (err) reject(err);
                resolve(reply);
            });
        });

        if (!data) {
            // 如果Redis中没有数据,则插入MySQL
            const connection = mysql.createConnection({
                host: 'localhost',
                user: 'root',
                password: 'password',
                database: 'testdb'
            });

            connection.connect();

            const insertQuery = 'INSERT INTO table_name (column_name) VALUES (?)';
            connection.query(insertQuery, ['value'], (err, results) => {
                if (err) throw err;
                console.log('Data inserted into MySQL');
                connection.end();
            });
        }

        // 断开Redis连接
        client.quit(() => {
            console.log('Redis client disconnected');
        });

        res.send(data || 'No data found in Redis');
    } catch (err) {
        console.error('Error handling request:', err);
        res.status(500).send('Internal Server Error');
    }
}

// 示例请求处理
handleRequest({}, {}).then(() => {
    console.log('Request handled');
});

分析与解决

  1. 问题原因

    • 可能是由于某些地方存在未捕获的异常,导致连接没有正确地关闭。
    • client.quit() 方法只是请求Redis客户端断开连接,但并不保证立即断开。
  2. 解决方案

    • 确保在所有可能的异常情况下都能正确关闭连接。
    • 使用client.disconnect()方法替代client.quit(),它会立即断开连接。

修改后的代码

client.disconnect(() => {
    console.log('Redis client disconnected');
});

通过上述修改,可以确保Redis连接在处理完请求后被正确断开。希望这能帮助到遇到类似问题的朋友!


你能发个redis+nodejs的存值取值的示例么?

根据你的描述,Redis 连接没有正常断开的问题可能是由于客户端并没有完全断开连接。client.quit() 方法应该能够正确关闭 Redis 连接,但有时候可能会因为某些异步操作导致连接没有完全断开。

以下是一些可能的解决方案:

  1. 确保所有异步操作完成后再调用 client.quit():

    • 确保在调用 client.quit() 之前所有的异步操作都已经完成。例如,在执行完插入 MySQL 的操作后,再调用 client.quit()
  2. 使用 Promise 或 async/await:

    • 使用 async/await 可以更好地控制异步操作的顺序。例如:
      const redis = require('redis');
      const mysql = require('mysql');
      
      const client = redis.createClient();
      const db = mysql.createConnection({
        host: 'localhost',
        user: 'root',
        password: 'password',
        database: 'test'
      });
      
      async function handleRequest() {
        try {
          await new Promise((resolve, reject) => {
            client.get('someKey', (err, reply) => {
              if (err) return reject(err);
              resolve(reply);
            });
          });
      
          // 插入 MySQL
          db.query('INSERT INTO someTable SET ?', { someColumn: 'someValue' }, (err, results) => {
            if (err) throw err;
          });
      
          // 断开连接
          client.quit();
          db.end();
        } catch (error) {
          console.error(error);
        }
      }
      
      handleRequest();
      
  3. 检查是否有未处理的错误:

    • 确保在每个回调函数中都有错误处理机制。例如,在 Redis 和 MySQL 的回调函数中添加错误处理:
      client.get('someKey', (err, reply) => {
        if (err) {
          console.error('Redis error:', err);
          client.quit();
          return;
        }
        // 处理回复
      });
      
      db.query('INSERT INTO someTable SET ?', { someColumn: 'someValue' }, (err, results) => {
        if (err) {
          console.error('MySQL error:', err);
          db.end();
          return;
        }
        // 处理结果
      });
      

通过上述方法,你可以确保在所有操作完成后正确地断开 Redis 和 MySQL 的连接。

回到顶部