我正在将Redis发布/订阅系统转换为Redis流,以便可以为服务器发送的事件添加一些容错功能。
订阅传统方式很简单:
import { createClient } from 'redis';
const redisOptions = {
url: `${process.env.REDIS_URL}/0`
}
const redis = createClient(redisOptions);
redis.setMaxListeners(100000);
redis.on("message", (channel, message) => {
console.log(channel);
console.log(message);
});
redis.subscribe('foo');
这将永久阻止并保持连接打开。在这种情况下,发布到redis将添加到您的日志中。
const json = { a: 1, b: 2 };
redis.publish('foo', JSON.stringify(json));
切换到流时,您使用XREAD
而不是订阅,并且使用XADD
而不是发布,并且数据有很大的不同。我苦苦挣扎的部分是障碍。
redis.xread('BLOCK', 0, 'STREAMS', 'foo', '$', (err, str) => {
if (err) return console.error('Error reading from stream:', err);
str.forEach(message => {
console.log(message);
});
}
发送邮件时,第一条邮件由我的“订阅”接收,但没有进一步的邮件记录。
答案 0 :(得分:1)
说实在的,我只问了这个问题,因为google对我不利,而且我找不到其他人发布有关此问题的信息。希望这会有所帮助!
因此,XREAD
仅在初始呼叫时阻塞。它会坐下来等待一段设定的时间(如果将时间设置为0,则将无限期地等待),但是一旦它接收到数据,就认为它的职责已完成,并且解除阻塞。为了使“订阅”保持活动状态,您需要使用流中的最新ID再次调用XREAD
。这将替换我们传递的初始$
值。
递归似乎是一个完美的解决方案:
const xread = ({ stream, id }) => {
redis.xread('BLOCK', 0, 'STREAMS', stream, id, (err, str) => {
if (err) return console.error('Error reading from stream:', err);
str[0][1].forEach(message => {
id = message[0];
console.log(id);
console.log(message[1]);
});
xread({ stream, id })
});
}
xread({ stream: 'asdf', id: '$' })