Node-redis: 流水线

创建于 2014-01-13  ·  9评论  ·  资料来源: NodeRedis/node-redis

嗨,大家好,

如何以编程方式在 node_redis 中启用流水线?

我看到文档说在大多数情况下它会自动发生 - 我想了解有没有办法在 node_redis 中以编程方式从应用程序代码中强制它

[ ec2-user@devops ~]$ redis-benchmark -n 100000 -t set,get -P 16 -q -h 10.0.1.10
SET:每秒 199600.80 个请求
GET:每秒 193050.19 个请求

[ ec2-user@devops ~]$ redis-benchmark -n 100000 -t set,get -q -h 10.0.1.12
SET:每秒 14098.41 个请求
GET:每秒 13743.82 个请求

它在 Redis 节点上相差 10 倍以上。

谢谢,
德米特里

Feature Request fixed / done

最有用的评论

所有命令都是“流水线”发送的,但由于一两个原因,这些命令永远不会在同一个流水线写帧中发送:

  1. sismember 的回调是调用 hgetall 调用的原因——因此您隐式地阻止了这些命令在任何给定的 sismember 调用中被流水线化。 在 Redis 回复之前不会调用回调。
  2. 如果baseclient是不同的 Redis 客户端,它们可能_NEVER_共享相同的管道。

命令需要从相同的上下文* 执行才能看到流水线的任何好处。 例如类似于 redis 流水线文档中的 PING 示例:

// These commands will all be pipelined together:
client.ping()
client.ping()
client.ping()
client.ping(function () {
  // This would *NEVER* be in the same pipeline frame as the other four because it requires a reply to be received first
  client.ping()
})

* 或者如果发送速度比 Redis 回复速度快,则从单独的上下文中发送,但从不回复相关上下文

所有9条评论

是通过 client.multi 和 multi.exec 命令完成的吗?

@saritasa - 流水线是自动的。 它总是发生在客户端内部。 您不需要使用 multi 或 exec 来启用它。

嗨,布莱斯,

  1. 我很困惑,那么 node_redis 中“多”函数的目的是什么?
  2. 用于自动流水线化命令的算法是什么?

谢谢,
德米特里

多操作来自 Redis 协议规范,它们在流水线之外具有事务性目的: http :

就流水线的工作方式而言: http :

谢谢 Bryce,我了解http://redis.io/topics/pipelining 的工作原理。 在 node.js 应用程序中 - 应如何构建代码以便对请求进行流水线处理?

所以在下面的例子中

hgetall & expire - 是否流水线化? 其中一个调用是内部回调。


函数 getByID(table, id, next) {
if (!success) return setTimeout(function () {
getByID(table, id, next);
}, 2000);

var end = utils.getEndTime(),
    base = getBase(),
    client = getClient(PK2str(table, id)),
    key = getHashID(table, id);

base.sismember(table, key, function (err, val) {
    if (err || !val) return next();

    client.hgetall(key, function (err, val) {
        if (err || !val) return next(new Error('Expired'), id);

        val = arrays_parse(table, val);
        next(null, val);
        client.expire(key, cfg.ttl.shards);

        if (!exports.silent) {
            profiler.log('cache', {
                'table': table,
                'id': key,
                'method': 'getByID',
                'data': val,
                'time': end()
            });
        }
    });  
});

}

所有命令都是“流水线”发送的,但由于一两个原因,这些命令永远不会在同一个流水线写帧中发送:

  1. sismember 的回调是调用 hgetall 调用的原因——因此您隐式地阻止了这些命令在任何给定的 sismember 调用中被流水线化。 在 Redis 回复之前不会调用回调。
  2. 如果baseclient是不同的 Redis 客户端,它们可能_NEVER_共享相同的管道。

命令需要从相同的上下文* 执行才能看到流水线的任何好处。 例如类似于 redis 流水线文档中的 PING 示例:

// These commands will all be pipelined together:
client.ping()
client.ping()
client.ping()
client.ping(function () {
  // This would *NEVER* be in the same pipeline frame as the other four because it requires a reply to be received first
  client.ping()
})

* 或者如果发送速度比 Redis 回复速度快,则从单独的上下文中发送,但从不回复相关上下文

现在知道了 - 谢谢! 这是非常有价值的评论!

我认为node_redis“自动流水线”不是redis官方提到的流水线。

这个时间称为RTT(往返时间)。 当客户端需要连续执行许多请求时(例如,将许多元素添加到同一个列表,或使用许多键填充数据库),很容易看出这会如何影响性能。 例如,如果 RTT 时间为 250 毫秒(在 Internet 上的链接非常慢的情况下),即使服务器能够每秒处理 10 万个请求,我们也将能够每秒最多处理四个请求。
如果使用的接口是环回接口,则RTT要短得多(例如我的主机报告ping 127.0.0.1 0,044毫秒),但如果您需要连续执行多次写入,它仍然很多。

官方redis的pipelining的意思是将多个命令组合起来,发送一次,以抵消RTT造成的延迟,node_redis没有解决这个问题。 而 node_redis 中的“自动流水线”实际上是通过使用 Node 的异步编程模型在同一时间发送尽可能多的命令。

这是一篇讨论这个问题的好文章。 http://informatikr.com/2012/redis-pipelining.html

@Vizwind @saritasa .multi和 .batch 都使用流水线作为从 2.2 版开始的想法。

此页面是否有帮助?
0 / 5 - 0 等级