假设您想在Redis中插入多个 db,并且要插入和/或删除数据。你有一个流动;
我使用一个名为 redisClient 的变量,基本上创建为;
redisClient = redis.createClient();
在选择新的数据库时,我使用选择命令和额外的预警回调,所以我的选择命令就像;
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请求并即将进入生产模式。该模型可能面临哪些问题?
答案 0 :(得分:12)
就像Carl Zulauf said一样,最好打开3个不同的连接(每个数据库一个):
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个)连接。
N.B。将它全部放入一个节点模块也是个好主意:
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
将被初始化。
答案 1 :(得分:11)
对3个不同的数据库使用3个连接是正确的方法。有额外连接打开的开销,但开销非常小。
通过数百个开放连接,开销将成为一个问题。我不确定您将运行多少个应用程序实例,但每个进程只猜测3个连接,您将无法获得有问题的数字。
答案 2 :(得分:5)
如果Google将您带到这里,请帮个忙:不要使用多个数据库支持。使用命名空间密钥或多个redis实例。
我自己在异步环境中遇到多个数据库支持后就这么说了。最后,我访问了Freenode上的#redis,并参考了Redis的作者Salvatore Sanfilippo的以下声明:
我认为Redis的多个数据库错误是Redis中最糟糕的决定 设计......我希望如此 在某些时候,我们可以放弃多个DB支持,但我认为 可能为时已晚,因为有很多人依赖于此 他们的工作特色。
https://groups.google.com/d/msg/redis-db/vS5wX8X4Cjg/8ounBXitG4sJ
在依赖 功能之前,你真的想要三思而后行。
答案 3 :(得分:2)
除了为3个不同的数据库设置3个不同的连接外,您还可以使用MULTI/EXEC
块进行此操作:
redisClient.multi().select(1).set("my_key_in_db_1","myval").exec()
答案 4 :(得分:1)
为每个数据库使用一个实例是正确的方法。但是,如果您需要重用或限制昂贵的资源(如数据库连接),那么数据库连接池可能是一个不错的选择。我们假设我们选择generic-pool(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);
});
});