Я использую общий Redis для хранения данных почти из 60 систем. Этот общий Redis используется для связи между всеми машинами. Сначала казалось, что все работает нормально, но когда я увеличил количество машин с 60 до 80, количество подключений к redis увеличилось, и после этого он не начал принимать больше подключений, что вызвало большую проблему.
Когда я начал отлаживать проблему с помощью ‘netstat -na | grep 6379 ‘Я обнаружил, что всякий раз, когда мы подключаемся к redis, он открывает соединение TCP / IP на конкретном порту, не освобождает это соединение и сохраняет это соединение в состоянии TIME_WAIT почти 60 секунд даже после вызова $ redis-> quit (). (используя предисловую библиотеку PHP)
Методы, которые я пытался преодолеть эту проблему:
1) Я пытался уменьшить время ожидания в / proc / sys / net / ipv4 / tcp_fin_timeout, но это не было правильным решением.
2) Я перешел с PHP на nodejs и пробовал пул соединений в nodejs, но безуспешно. Вот пример кода
app.get('/setinredis',function(req,res){
var poolRedis = require('pool-redis')({
'host': 'localhost',
'password': '',
'maxConnections': 5
});
poolRedis.getClient(function(client, done) {
client.get('somekey', function(err, value) {
console.log('value from redis is:', value);
done();
res.send({message:"Done"});
});
});
});
Есть ли способ эффективно решить эту проблему или альтернатива Redis с функциональностью структуры данных.
Любая помощь будет оценена.
Проблема в том, что вы создаете пул каждый раз, когда кто-то бьет /setinredis
конечная точка. Это означает, что если вы достигнете этой конечной точки 1000 раз, вы создадите 1000 пулов. Переместите создание пула за пределы маршрута:
var poolRedis = require('pool-redis')({
'host': 'localhost',
'password': '',
'maxConnections': 5
});
app.get('/setinredis',function(req,res){
poolRedis.getClient(function(client, done) {
client.get('somekey', function(err, value) {
console.log('value from redis is:', value);
done();
res.send({message:"Done"});
});
});
});
edit: в качестве примечания, ваш вопрос сбивает с толку, поскольку он относится к PHP, но код находится в Node.js.
Пожалуйста, попробуйте этот способ, он должен работать нормально.
=== controller.js ===
const user = require('./user')()
user.getUser('12345')
.then(user => {
console.log(user.xxxx)
})
=== user.js ===
const redis = require('redis'),
Promise = require('bluebird')
function getUser(id) {
return redis.getAsync(id)
.then(user => JSON.parse(user))
}
module.exports = () => {
Promise.promisifyAll(redis.RedisClient.prototype)
Promise.promisifyAll(redis.Multi.prototype)
return new Promise((resolve, reject) => {
const client = redis.createClient(REDIS_SERVER)
client.on('connect', onConnect)
client.on('error', err => {
throw err
})
function onConnect() {
return resolve({
getUser
})
}
})
}
Это как-то связано с таймаутами TCP fin (по умолчанию 60 секунд в Linux). Возможно, вы не повторно используете соединения, а каждый раз открываете новое, это совершенно нормально. Но если вы делаете это так быстро, что рискуете использовать все доступные порты. Вы должны использовать эти параметры sysctl, чтобы уменьшить таймауты tcp fin и включить соединение tcp_reuse.
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 10 #value is in seconds
tcp_tw_reuse
Повторное использование TCP позволяет ядру Linux восстановить слот соединения из соединения в состоянии TIME_WAIT и перераспределить его в новое соединение. Повторное использование сокетов может быть очень эффективным для снижения нагрузки на сервер.
tcp_fin_timeout
Определяет время, которое должно пройти, прежде чем TCP / IP сможет освободить закрытое соединение и повторно использовать его ресурсы. В этом состоянии TIME_WAIT повторное открытие соединения с клиентом обходится дешевле, чем установление нового соединения.
Ссылка: http://www.speedguide.net/articles/linux-broadband-tweaks-121