node.js 中的 Redis 错误

Redis error in node.js

我在 Node.js 中使用 Redis,在实时服务器上部署时它开始崩溃并显示以下错误消息:

每秒请求数更多。

at Object.replyToObject [as reply_to_object] (/home/ubuntu/webservices/node_modules/redis/lib/utils.js:7:15)
at RedisClient.handle_reply (/home/ubuntu/webservices/node_modules/redis/index.js:319:23)
at multi_callback (/home/ubuntu/webservices/node_modules/redis/lib/multi.js:79:43)
at Command.callback (/home/ubuntu/webservices/node_modules/redis/lib/multi.js:116:9)
at normal_reply (/home/ubuntu/webservices/node_modules/redis/index.js:726:21)
at RedisClient.return_reply (/home/ubuntu/webservices/node_modules/redis/index.js:824:9)
at JavascriptRedisParser.returnReply (/home/ubuntu/webservices/node_modules/redis/index.js:192:18)
at JavascriptRedisParser.execute (/home/ubuntu/webservices/node_modules/redis/node_modules/redis-parser/lib/parser.js:553:10)
Socket.<anonymous> (/home/ubuntu/webservices/node_modules/redis/index.js:274:27)
emitOne (events.js:116:13)
Socket.emit (events.js:211:7)
addChunk (_stream_readable.js:263:12)
readableAddChunk (_stream_readable.js:250:11)
at Socket.Readable.push (_stream_readable.js:208:10)
at TCP.onread (net.js:594:20)

我已经编写了打开和关闭 Redis 连接的通用代码,并尝试重用连接。 (不确定重用它是否正确)。

我正在使用 Redis“^2.7.1”并在 Ubuntu 上本地安装了 Redis。

我可以进入 Redis 控制台并查看存储的密钥。但不确定为什么它会非常频繁地给出上述错误信息。我正在使用 pm2 模块,所以它会在崩溃后重新启动。

下面是Node.js

中的Redis代码
var Promise = require('bluebird');
var Redis = Promise.promisifyAll(require('redis'));

// Global (Avoids Duplicate Connections)
var redisClient = null;
var redisMultiClient = null;

// Make the below functions as private
function openRedisConnection() {
    if (redisClient && redisClient.connected)
        return redisClient;

    if (redisClient)
        redisClient.end(); // End and open once more

    redisClient = Redis.createClient(6379,process.env.REDIS_URL);
    redisClient.selected_db = 1;
    return redisClient;
}

function openMultiRedisConnection() {
    if (redisMultiClient && redisMultiClient._client.connected) {
        redisMultiClient._client.selected_db = 0;
        return redisMultiClient;
    }

    if (redisMultiClient)
        redisMultiClient.quit(); // End and open once more

    redisMultiClient = Redis.createClient(6379,process.env.REDIS_URL).multi();
    redisMultiClient._client.selected_db = 0;
    return redisMultiClient;
}

function getExpiryTime(key) {
    return 120; // testing
}


module.exports = {
    /**
     * Get Key-Value Pair
     */
    getRedisValue: function (keys) {
        return openRedisConnection().mgetAsync(keys);
    },
    /**
     * Set Key-Value Pair
     */
    setRedisValue: function (key, value) {
        return openRedisConnection()
            .setAsync(key, value, 'EX', getExpiryTime(key))
            .then(function (result) {
                return Promise.resolve(result);
            });
    },

    getV2MultiRedisValue: function (keyList) {
        let redisMultiClientObj = openMultiRedisConnection();
        redisMultiClientObj._client.selected_db = 2;

        redisMultiClientObj.hgetallAsync(keyList);

        return redisMultiClientObj.execAsync()
            .then(function (results) {
                return Promise.resolve(results);
            });
    },

    setV2MultiRedisValue: function (key, redisList) {
        let expiryTime = getExpiryTime(key);
        let redisMultiClientObj = openMultiRedisConnection();
        redisMultiClientObj._client.selected_db = 2;

        for (let item of redisList) {
            redisMultiClientObj.hmsetAsync(item.key, item.value);
            redisMultiClientObj.expireAsync(item.key, expiryTime);
        }
        return redisMultiClientObj.execAsync()
        .then(function (results) {
            return Promise.resolve(results);
        });
    }
};

client.multi([commands])不开多连接,只是指出因为函数openMultiRedisConnection是误导。

根据参考资料,您使用了多个错误

client.multi([commands])

MULTI commands are queued up until an EXEC is issued, and then all commands are run atomically by Redis. The interface in node_redis is to return an individual Multi object by calling client.multi(). If any command fails to queue, all commands are rolled back and none is going to be executed (For further information look at transactions).

多个returns一个单独的Object,在调用.exec后再次使用它不太好。

我不知道为什么您需要一个数据库,但您正在使用 selected_db 和全局客户端变量更改数据库,这很糟糕!并可能导致很多问题!(数据不一致,冲突等)。 您可以使用 client.select(callback) 来更改数据库,但这似乎又是个坏主意。

这部分代码没有理由与不这样做完全一样。

 .then(function (result) {
    return Promise.resolve(result);
  });

你应该只用一个数据库就可以了。

   var Promise = require('bluebird');
var Redis = Promise.promisifyAll(require('redis'));

// Global (Avoids Duplicate Connections)
var redisClient = [];


// Make the below functions as private
function openRedisConnection( {
    if (redisClient && redisClient.connected)
        return redisClient;

    if (redisClient)
        redisClient.end(); // End and open once more

    redisClient = Redis.createClient(6379,process.env.REDIS_URL,{"db":1});

    return redisClient;
}


function getExpiryTime(key) {
    return 120; // testing
}


module.exports = {
    /**
     * Get Key-Value Pair
     */
    getRedisValue: function (keys) {
        return openRedisConnection().mgetAsync(keys);
    },
    /**
     * Set Key-Value Pair
     */
    setRedisValue: function (key, value) {
        return openRedisConnection()
            .setAsync(key, value, 'EX', getExpiryTime(key));

    },

    getV2MultiRedisValue: function (keyList) {

         let redisClient = openRedisConnection();

        //no need to open multi here....
        let multi = redisClient.multi();

        multi.hgetallAsync(keyList);

        return multi.execAsync();

    },

    setV2MultiRedisValue: function (key, redisList) {
        let expiryTime = getExpiryTime(key);
        let redisClient = openRedisConnection();

        let multi = redisClient.multi();

        for (let item of redisList) {
            multi.hmsetAsync(item.key, item.value);
            multi.expireAsync(item.key, expiryTime);
        }

        return multi.execAsync();

    }
};