Node & Redis: Redis 客户端

15

假设您在Redis中有多个数据库,希望插入和/或删除数据。您的流程如下:

  • 将数据插入到DB#1
  • 在第一个插入的回调之后执行某些操作,然后将数据插入到DB#2
  • 在第二个插入的回调之后再次执行一些操作,并最终将数据插入到DB#3

我使用一个名为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中的DB使用独立的redisClients会有多合理。所以它会像这样:

然而,事情经常混淆。请注意,变量redisClient仅分配了一次,然后在整个应用程序中使用。现在我想知道,为每个Redis数据库使用单独的redisClients是否合理。因此,它将是这样的;

redisClientForDB1 = redis.createClient();
redisClientForDB2 = redis.createClient();
redisClientForDB3 = redis.createClient();

我在想,如果一个应用程序将每秒接收到 4K个请求 并即将进入生产模式,这是否合理,或者这是否是正确的方式。这种模型可能会面临哪些问题

5个回答

15

正如卡尔·祖劳夫(Carl Zulauf)所说,最好打开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,Node进程将会打开3个(仅限3个)连接。
注意:把它们全部放到一个Node模块中也是个好主意。
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连接(因为Node缓存require调用):

require('./lib/my_redis').init(function(err) {
  if (err) throw err;
  server.listen();
});

然后当在任何一个模块中调用require('./lib/my_redis').DB1.set('key','val')时,DB1将已经被初始化。


11

使用3个连接来连接3个不同的数据库是正确的做法。保持额外连接处于打开状态会产生一些开销,但这种开销非常小。

如果打开了数百个连接,开销将开始成为一个问题。我不确定您将运行多少应用程序实例,但猜测每个进程只需要3个连接,您不会遇到任何问题。


没错!为每个连接使用单独的客户端是正确的做法 :) - mekwall

7
如果你是通过谷歌来到这里的,请别使用多个数据库支持。使用命名空间键或多个Redis实例。
我曾在异步环境下与多个数据库支持进行斗争。最后我毫无头绪地在Freenode的#redis频道中发帖,得到了Redis的作者Salvatore Sanfilippo的以下声明:
"I consider Redis multiple database errors my worst decision in Redis design at all... I hope that at some point we can drop the multiple DBs support at all, but I think it is probably too late as there is a number of people relying on this feature for their work."
你真的需要仔细考虑一下,是否要依赖作者最后悔的功能。

使用这个功能会遇到哪些实际问题? - UpTheCreek
1
你必须将整个服务作为回调函数启动,以响应DB选择命令。当多个配置元素以这种方式工作时,将主要配置回调变得很尴尬。首先,它使得在配置错误的情况下无法快速失败。 - sheldonh

2
今日免费次数已满, 请开通会员/明日再来
redisClient.multi().select(1).set("my_key_in_db_1","myval").exec()

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

你可以使用 mysql 模块本身来进行连接池操作:https://github.com/felixge/node-mysql/#pooling-connections - Nirmal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接