编写一个简单的 Node redis 循环的更好方法(使用 ioredis)?

Xed*_*iDC 4 redis node.js node-redis

所以,我很长一段时间都在学习其他语言的 JS/Node 方式。

我有一个从 redis 通道读取的微型微服务,将它临时存储在一个工作通道中,完成工作,删除它,然后继续前进。如果频道中有更多内容,它会立即重新运行。如果没有,它会设置超时并在 1 秒后再次检查。

它工作正常......但超时轮询似乎不是解决这个问题的“正确”方法。而且我还没有找到太多关于使用 BRPOPLPUSH 尝试阻止(与 RPOPLPUSH 相比)并在 Node 中等待...或其他类似选项的信息。(Pub/Sub 不是这里的一个选项......这是唯一的侦听器,它可能并不总是在侦听。)

这是我正在做的事情的简短本质:

var Redis = require('ioredis');
var redis = new Redis();

var redisLoop = function () {
    redis.rpoplpush('channel', 'channel-working').then(function (result) {
        if (result) {
            processJob(result); //do stuff

            //delete the item from the working channel, and check for another item
            redis.lrem('channel-working', 1, result).then(function (result) { });
            redisLoop();
        } else {
            //no items, wait 1 second and try again
            setTimeout(redisLoop, 1000);
        }
    });
};

redisLoop();
Run Code Online (Sandbox Code Playgroud)

我觉得我错过了一些非常明显的东西。谢谢!

Igo*_*ush 5

BRPOPLPUSH不会在Node 中阻塞,而是在client 中阻塞。在这种情况下,我认为这正是摆脱投票所需要的。

var Redis = require('ioredis');
var redis = new Redis();

var redisLoop = function () {
    redis.brpoplpush('channel', 'channel-working', 0).then(function (result) {
        // because we are using BRPOPLPUSH, the client promise will not resolve
        // until a 'result' becomes available
        processJob(result);

        // delete the item from the working channel, and check for another item
        redis.lrem('channel-working', 1, result).then(redisLoop);
    });
};

redisLoop();
Run Code Online (Sandbox Code Playgroud)

请注意,这redis.lrem是异步的,因此您应该使用它lrem(...).then(redisLoop)来确保仅在从channel-working.

  • 没问题!顺便说一句,重要的是在这里 Node 中没有 I/O 阻塞。你可以同时做其他工作。但是,如果您尝试重用相同的 `redis` 客户端来并发调用 Redis,那么您的循环会_会_干扰。我提到是因为这在最近的一个项目中让我感到困惑,我意识到我需要第二个“非阻塞”客户端来运行命令,而第一个客户端会阻塞。 (3认同)