[英]Redis / Node.js - 2 clients (1 pub/sub) causing issues with writes
[英]Node & Redis: Redis Clients
假设您在Redis中有多个数据库,您想插入和/或删除数据。 你有一个流动;
我使用一个名为redisClient的变量,基本上创建为;
redisClient = redis.createClient();
虽然选择一个新的数据库,我用SELECT命令与格外小心前的回调,所以我选择指令等;
redisClient.select(1, function(err) {
//Some programming logic (Insertion, deletion and stuff)
redisClient.select(2, function(err) {
//Do some additional programming logic (Insertion, deletion and stuff)
}
});
然而事情变得不断混合。 我想要注意的是,redisClient变量只被分配了一次,后来在整个应用程序中使用。 现在我想知道,对Redis中的每个数据库使用单独的redisClients是多么合理。 所以它会是这样的;
redisClientForDB1 = redis.createClient();
redisClientForDB2 = redis.createClient();
redisClientForDB3 = redis.createClient();
我想知道它是否合理,或者对于每秒接收4K请求并即将进入生产模式的应用程序来说这是一种正确的方法。 这个型号可能面临哪些问题 ?
正如Carl Zulauf所说 ,最好打开3个不同的连接(每个DB一个):
redisClient = {
DB1: redis.createClient(),
DB2: redis.createClient(),
DB3: redis.createClient()
};
在服务器初始化期间最好打开所有连接一次:
async.parallel([
DB1.select.bind(DB1, 1),
DB2.select.bind(DB2, 2),
DB3.select.bind(DB3, 3)
], next);
因此,在创建redisClient
对象并初始化它之后,您可以使用它来处理所有redis操作。
如果您将以这种方式使用redis,则节点将为每个节点进程打开3个(且仅3个)连接。
NB将它全部放入一个节点模块也是一个好主意:
module.exports = {
DB1: redis.createClient(),
DB2: redis.createClient(),
DB3: redis.createClient(),
init: function(next) {
var select = redis.RedisClient.prototype.select;
require('async').parallel([
select.bind(this.DB1, 1),
select.bind(this.DB2, 2),
select.bind(this.DB3, 3)
], next);
}
};
然后,您将能够通过调用init
函数初始化所有redis连接(因为节点缓存require
调用):
require('./lib/my_redis').init(function(err) {
if (err) throw err;
server.listen();
});
然后当require('./lib/my_redis').DB1.set('key','val')
将在你的任何模块中调用DB1
将被初始化。
对3个不同的数据库使用3个连接是正确的方法。 打开额外连接会产生开销,但开销非常小。
有了数百个开放连接,开销就会成为一个问题。 我不确定您将运行多少个应用程序实例,但每个进程只猜测3个连接,您将无法获得有问题的数字。
如果谷歌把你带到这里,请帮个忙:不要使用多个数据库支持。 使用命名空间密钥或多个redis实例。
在我自己在异步环境中努力解决多个数据库支持之后,我这样说了。 最后,我访问了Freenode上的#redis,并参考了Redis的作者Salvatore Sanfilippo的以下声明:
我认为Redis的多个数据库错误是我在Redis设计中最糟糕的决定...我希望在某些时候我们可以放弃多个DB支持,但我认为可能为时已晚,因为有很多人依赖这个功能对他们的工作。
https://groups.google.com/d/msg/redis-db/vS5wX8X4Cjg/8ounBXitG4sJ
你真的想依靠笔者感到遗憾的是大部分的功能之前,要三思而后行。
您可以使用MULTI/EXEC
块来代替3个不同DB的3个不同连接:
redisClient.multi().select(1).set("my_key_in_db_1","myval").exec()
为每个数据库使用一个实例是正确的方法。 但是,如果您需要重用或限制昂贵的资源(如数据库连接),那么数据库连接池可能是一个不错的选择。 假设我们选择泛型池 (node.js的通用池解决方案),您可以这样编码:
// Step 1 - Create pool using a factory object
var mysql= require('mysql'),
generic_pool = require('generic-pool');
var pool = generic_pool.Pool({
name: 'mysql pool 1',
min: 1,
max: 50,
idleTimeoutMillis : 30000,
create : function(callback) {
var Client = mysql.Client;
var c = new Client();
c.user = 'myusername';
c.password = 'mypassword';
c.database = 'mydb';
c.connect();
callback(null, c);
},
destroy : function(client) { client.end(); }
});
// Step 2 - Use the pool in your code to acquire/release resources
pool.acquire(function(err, client) {
if (err) {
// handle error
return res.end("CONNECTION error: " + err);
}
client.query("select * from foo", [], function() {
// return object back to pool
pool.release(client);
});
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.