Я использую 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);
});
}
};
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();
}
};
let multi = redisClient.multi();
это верно ? просто запутался