Ошибка Redis в node.js

1

Я использую Redis в Node.js и при развертывании на реальном сервере он начал сбой с сообщением об ошибке:

Количество запросов больше в секунду.

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" и установил Redis локально на Ubuntu.

Я могу войти в консоль Redis и посмотреть сохраненные ключи. Но не уверен, почему это часто приводит сообщения об ошибках. Я использую модуль pm2, поэтому он перезапускается после сбоя.

Ниже приведен код Redis в Node.js

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);
        });
    }
};
Теги:
redis
node-redis

1 ответ

1
Лучший ответ

client.multi([commands]) не открывают несколько соединений, просто указывая, потому что функция openMultiRedisConnection вводит в заблуждение.

Вы используете mulit wrong, за ссылку

client.multi([команды])

Команды MULTI помещаются в очередь до выдачи EXEC, а затем все команды запускаются атомарно с помощью Redis. Интерфейс в node_redis должен возвращать отдельный объект Multi, вызывая client.multi(). Если какая-либо команда не может стоять в очереди, все команды откатываются назад, и никто не будет выполнен (для получения дополнительной информации смотрите транзакции).

Multi возвращает отдельный объект и не очень хорошо его использовать после .exec.

Я не знаю, почему вам нужно больше одной базы данных, но вы меняете базу данных с помощью selected_db и на глобальную клиентскую переменную, и это BAD! и может вызвать множество проблем! (несогласованность данных, конфликт и т.д.). Вы можете использовать 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();

    }
};
  • 0
    спасибо за ответ .. 1 .then (function (result) {return Promise.resolve (result);}); на самом деле, перед тем, как обещание будет выполнено, есть некоторая бизнес-логика, которая удалена для ясности, так что это нормально .. 2 разных БД должны проверить, могу ли я слиться. 3 Мульти концепция позвольте мне реализовать и вернуться к вам как можно скорее
  • 0
    // здесь не нужно открывать мульти ... Вы упомянули этот комментарий в функции getV2MultiRedisValue и сказали, что let multi = redisClient.multi(); это верно ? просто запутался
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню