节点& Redis:Redis客户

时间:2012-12-20 11:25:13

标签: javascript performance api node.js redis

假设您想在Redis中插入多个 db,并且要插入和/或删除数据。你有一个流动;

      
  • 将数据插入 DB#1
  •   
  • 第一次插入后回调做一些事情并将数据插入 DB#2
  •   
  • 第二次插入后回调再次做一些事情,最后将数据插入 DB#3

我使用一个名为 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请求并即将进入生产模式。该模型可能面临哪些问题

5 个答案:

答案 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);
    });
});