跳到主要内容

认识

2025年01月07日
柏拉文
越努力,越幸运

一、认识


Redis 发布订阅(Pub/Sub 是一种消息通信模式,允许不同的客户端(发布者和订阅者)进行解耦通信,广泛应用于消息推送、事件通知等场景。

Redis 发布订阅(Pub/Sub)概念:

  1. 频道(Channel: 一个逻辑上的消息通道,客户端可以订阅该频道,接收从该频道发布的消息。

  2. 发布(Publish:将消息发送到指定频道的操作。

  3. 订阅(Subscribe: 客户端订阅一个或多个频道,接收相应频道的消息。

Redis 发布订阅(Pub/Sub)工作:

  1. Redis 服务器, Redis 作为中介,负责接收发布者发送的消息,并将这些消息转发给所有订阅该频道的客户端。

  2. 发布者(Publisher, 发布者将消息发送到一个特定的频道(Channel)。消息本身并不直接发送到订阅者,而是通过 Redis 进行传递。

  3. 订阅者(Subscriber, 订阅者可以订阅一个或多个频道。任何发布到这些频道的消息都会被 Redis 推送到所有订阅了这些频道的客户端。

Redis 发布订阅(Pub/Sub)特点:

  1. 无消息确认, 发布订阅是 火车头模式 的推送,没有确认机制。如果消息发送失败或订阅者未能及时处理,消息将丢失。

  2. 消息丢失, 如前所述,RedisPub/Sub 机制不持久化消息,因此如果订阅者在消息发布时未在线或未及时接收,消息将不会被保存。

二、语法


2.1 同线程

const Redis = require("ioredis");
const sub = new Redis();
const pub = new Redis();

sub.subscribe(/* ... */); // From now, `sub` enters the subscriber mode.
sub.on("message" /* ... */);

setInterval(() => {
// `pub` can be used to publish messages, or send other regular commands (e.g. `hgetall`)
// because it's not in the subscriber mode.
pub.publish(/* ... */);
}, 1000);

2.2 异线程

发布者(Publisher

const Redis = require("ioredis");
const redis = new Redis();

setInterval(() => {
const message = { foo: Math.random() };
// Publish to my-channel-1 or my-channel-2 randomly.
const channel = `my-channel-${1 + Math.round(Math.random())}`;

// Message can be either a string or a buffer
redis.publish(channel, JSON.stringify(message));
console.log("Published %s to %s", message, channel);
}, 1000);

订阅者(Subscriber

const Redis = require("ioredis");
const redis = new Redis();

redis.subscribe("my-channel-1", "my-channel-2", (err, count) => {
if (err) {
// Just like other commands, subscribe() can fail for some reasons,
// ex network issues.
console.error("Failed to subscribe: %s", err.message);
} else {
// `count` represents the number of channels this client are currently subscribed to.
console.log(
`Subscribed successfully! This client is currently subscribed to ${count} channels.`
);
}
});

redis.on("message", (channel, message) => {
console.log(`Received ${message} from ${channel}`);
});

// There's also an event called 'messageBuffer', which is the same as 'message' except
// it returns buffers instead of strings.
// It's useful when the messages are binary data.
redis.on("messageBuffer", (channel, message) => {
// Both `channel` and `message` are buffers.
console.log(channel, message);
});