Redisのメッセージングパブリッシング・サブスクライブモードの入門から使いこなしまで詳しく解説【上級編】


ここに画像の説明を挿入

0. 序文

パブリッシュ-サブスクライブ パターン (パブリッシュ-サブスクライブ パターン) は、メッセージの送信者 (パブリッシャー) がメッセージを特定の受信者 (サブスクライバー) に直接送信するのではなく、メッセージをさまざまなカテゴリ (チャネル))、それらのカテゴリに登録しているすべての受信者にメッセージを送信します。パブリッシュ/サブスクライブ モデルは、リアルタイムのメッセージ プッシュ、ログ収集などの分散システムで広く使用されています。

Redis では、パブリッシュ/サブスクライブ モデルには、パブリッシャーとサブスクライバーという 2 つの主要な役割があります。パブリッシャは PUBLISH コマンドを通じて指定されたチャネルにメッセージを送信し、サブスクライバは SUBSCRIBE コマンドを通じて指定されたチャネルを購読/購読解除し、リスナー (コールバック) を通じてパブリッシャーによって送信されたメッセージを受信します。
次の図は、チャネル channel1 と、このチャネルにサブスクライブしている 3 つのクライアント (client2、client5、client1) 間の関係を示しています。
ここに画像の説明を挿入

新しいメッセージが PUBLISH コマンドを通じてチャネル channel1 に送信されると、このメッセージはそれにサブスクライブしている 3 つのクライアントに送信されます。

ここに画像の説明を挿入

1. 基本原則

Redis パブリッシュ/サブスクライブは、複数のクライアントがメッセージをパブリッシュおよびサブスクライブできるメッセージ通信モードです。Redis は、パブリッシュおよびサブスクライブ機能を実装するために次のコマンドを提供します。

  1. PUBLISH チャネル メッセージ: 指定されたチャネル チャネルにメッセージ メッセージを送信します。戻り値は、メッセージを受信した加入者の数です。
  2. SUBSCRIBE チャネル [チャネル …]: 1 つ以上のチャネル チャネルを購読すると、購読したチャネルに新しいメッセージが公開されるたびに、対応するメッセージが受信されます。
  3. UNSUBSCRIBE [channel [channel …]]: 1 つ以上のチャンネルから登録を解除します。チャンネルが指定されていない場合は、すべてのチャンネルから登録を解除します。
  4. PSUBSCRIBE パターン [パターン ...]: 指定されたパターン pattern に一致する 1 つ以上のチャネルをサブスクライブし、パターンに一致するチャネルに新しいメッセージがパブリッシュされるたびに、対応するメッセージが受信されます。
  5. PUNSUBSCRIBE [パターン [パターン ...]]: 指定されたパターン pattern に一致する 1 つ以上のチャネルからサブスクライブを解除します。パターンが指定されていない場合は、すべてのパターンからサブスクライブを解除します。
  6. PUBSUB サブコマンド [引数 [引数 …]]: 購読および公開システムのステータスを表示します。これを使用して、購読者数、チャンネル リストなど、購読および公開システムのさまざまな情報を取得できます。このうち、PUBLISH
    コマンドは指定されたチャネルにメッセージをパブリッシュするために使用され、SUBSCRIBE コマンドは 1 つ以上のチャネルをサブスクライブするために使用され、PSUBSCRIBE コマンドは指定されたモードを満たす 1 つ以上のチャネルをサブスクライブするために使用され、
    PUBSUBコマンドは、サブスクリプションおよび発行システムのステータスを表示するために使用されます。

1.1 チャネルベースのパブリッシュ/サブスクライブ

Redis のチャネルはメッセージの分類に相当し、チャネルには複数のサブスクライバを含めることができ、サブスクライバは複数のチャネルにサブスクライブすることもできます。Redis では、PUBLISH コマンドを使用して指定したチャネルにメッセージを送信し、SUBSCRIBE コマンドを使用して指定したチャネルをサブスクライブ/サブスクライブ解除し、リスナーを介してパブリッシャによって送信されたメッセージを受信します。

Redis コマンドライン インターフェイスでのチャネルベースのパブリッシュ/サブスクライブの例を次に示します。

# 订阅频道
127.0.0.1:6379> SUBSCRIBE news
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "news"
3) (integer) 1

# 发布消息
127.0.0.1:6379> PUBLISH news "Hello, world!"
(integer) 1

# 订阅者接收到消息
1) "message"
2) "news"
3) "Hello, world!"

Redis では、パブリッシュ/サブスクライブ モードの実装は Redis イベント メカニズムに基づいています。つまり、サブスクライバーは SUBSCRIBE コマンドを実行して、独自のリスナーを Redis サーバーのイベント ルーパーに追加します。 PUBLISH コマンドを通じて指定されたチャネルを使用すると、Redis サーバーはそのチャネルを聞いているすべてのサブスクライバにメッセージを送信します。

具体的には、Redis サーバーはイベント ループを維持し、すべてのクライアント リスナーをイベント ループに登録します。クライアントが SUBSCRIBE コマンドを通じてチャネルにサブスクライブすると、Redis サーバーはそのチャネルに関連付けられたイベント ハンドラーにクライアントのリスナーを追加し、そのイベント ハンドラーをイベント ルーパーに登録します。パブリッシャーが PUBLISH コマンドを通じて指定されたチャネルにメッセージを送信すると、Redis サーバーは、メッセージのパブリッシュとサブスクリプションを実現するために、そのチャネルに関連するイベント ハンドラー内のすべてのリスナーにメッセージを送信します。

1.2 パターンベースのパブリッシュ/サブスクライブ

Redis は、パターンに基づいた Pub/Sub もサポートしています。パターンは、1 つ以上のチャネルと一致する特別なチャネルです。Redis では、PSUBSCRIBE コマンドを使用して、指定されたパターンに一致するチャネルをサブスクライブ/サブスクライブ解除し、リスナーを介してパブリッシャーによって送信されたメッセージを受信します。

Redis コマンド ライン インターフェイスでのスキーマベースの pub/sub の例を次に示します。

# 订阅模式
127.0.0.1:6379> PSUBSCRIBE news.*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "news.*"
3) (integer) 1

# 发布消息
127.0.0.1:6379> PUBLISH news.world "Hello, world!"
(integer) 1

# 订阅者接收到消息
1) "pmessage"
2) "news.*"
3) "news.world"
4) "Hello, world!"

パターン ベースのパブリッシュ/サブスクライブは、チャネル ベースのパブリッシュ/サブスクライブと似ていますが、より柔軟なメッセージ フィルタリングとサブスクリプションを実現するために、サブスクライブ時に複数のチャネルを照合するためにワイルドカード (*) を使用できる点が異なります。

具体的には、クライアントが PSUBSCRIBE コマンドを通じてパターンをサブスクライブすると、Redis サーバーはパターンに一致するチャネルに関連するすべてのイベント ハンドラーにクライアントのリスナーを追加し、イベント ルーパー プロセッサにイベントを登録します。パブリッシャーが PUBLISH コマンドを通じてパターンに一致するチャネルにメッセージを送信すると、Redis サーバーはパターンに関連するイベント ハンドラー内のすべてのリスナーにメッセージを送信するため、パターン ベースのメッセージ パブリッシュとサブスクリプションが実現します。

2. Redis パブリッシュとサブスクライブの実践的な応用

2.1 Redis センチネル

Redis Sentinel は Redis の高可用性ソリューションであり、マスター ノードに障害が発生した場合、スレーブ ノードをマスター ノードに自動的に昇格させてフェイルオーバーを実現します。Redis Sentinel は、パブリッシュ/サブスクライブ メカニズムを使用して新しいノードを検出し、マスター ノード間で状態を交換します。クライアントは、特定のチャネルにサブスクライブすることでマスター ノードのフェイルオーバーのステータス情報を取得することもできます。

Redis Sentinel では、各 Sentinel ノードは定期的にメッセージをSentinel :hello チャネルに送信し、各 Sentinel ノードもこのチャネルにサブスクライブします。そのため、ノードがこのチャネルにメッセージを送信すると、他のノードはすぐにメッセージを受信できますこのノードをローカル ノード リストに追加します。さらに、メッセージがこのチャネルに送信されるたびに、メッセージにはノードのステータス情報が含まれる可能性があり、その後の Sentinel リーダー選出の基礎として使用されます。

クライアントの場合、+switch-master チャネルにサブスクライブすることで、マスター ノードのフェールオーバーのステータス情報を取得できます。Redis Sentinel がマスター ノードのフェイルオーバーを完了すると、マスター ノードのメッセージが公開され、クライアントはメッセージを受信して​​時間内に新しいマスター ノードに切り替えることができるため、システムの信頼性と可用性が確保されます。
ここに画像の説明を挿入

Redis Sentinel ノードは主にパブリッシュ/サブスクライブ メカニズムを使用して、新しいノードの検出を実現し、マスター ノード間でステータスを交換します。上の図に示すように、各 Sentinel ノードは定期的にメッセージをSentinel :hello チャネルに送信し、各 Sentinel はこのノードをサブスクライブします。このようにして、ノードがこのチャネルにメッセージを送信すると、他のノードはすぐにメッセージを受信できます。
このようにして、新しいノードが参加すると、このチャネルにメッセージを送信し、他のノードがそれを受信すると、ローカル リストにそのノードが存在しないと判断し、新しいノードとしてローカル ノード リストに追加できます。 。

さらに、メッセージがこのチャネルに送信されるたびに、ノードのステータス情報の内容を含めることができ、その後の Sentinel リーダー選出の基礎として使用できます。

上記はすべて Redis サーバーに関するものですが、クライアントについてはパブリッシュ/サブスクライブ メカニズムを使用することもできます。
Redis Sentinel がマスター ノードのフェイルオーバーを実行する場合、このプロセスの各段階はパブリッシュとサブスクライブを通じて外部から提供されます。
クライアントの場合は、切り替え後のマスター ノードをより重視し、時間内にマスター ノードの接続を切り替えることができます (この時点で古いノードに障害が発生し、操作指示を受け入れることができなくなります)。クライアントはサブスクライブできます。 +switch-master チャネルに追加すると、
マスター ノードのフェイルオーバー後に Redis Sentinel がマスター ノードのメッセージを公開します。

2.1 SpringBoot Redis のパブリッシュ/サブスクライブ

Spring Boot では、Spring Data Redis が提供する RedisMessageListenerContainer クラスと RedisTemplate クラスを通じて Redis パブリッシュ/サブスクライブ機能を実現できます。具体的な手順は次のとおりです。

  1. Redis と Spring Data Redis の依存関係を追加します。
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  1. Redis 接続情報を構成します。
spring.redis.host=localhost
spring.redis.port=6379
  1. RedisMessageListenerContainer インスタンスと RedisTemplate インスタンスを作成します。
@Configuration
public class RedisConfig {
    
    
    
    @Autowired
    private RedisConnectionFactory redisConnectionFactory;

    @Bean
    public RedisMessageListenerContainer messageListenerContainer() {
    
    
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(redisConnectionFactory);
        return container;
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
    
    
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        template.setDefaultSerializer(new StringRedisSerializer());
        return template;
    }
}
  1. メッセージ リスナーを作成します。
@Component
public class MessageListener implements MessageListenerAdapter {
    
    

    @Override
    public void onMessage(Message message, byte[] pattern) {
    
    
        String msg = (String) redisTemplate().getValueSerializer().deserialize(message.getBody());
        System.out.println("Received message: " + msg);
    }
}
  1. ニュースを購読する:
@Autowired
private RedisMessageListenerContainer container;

@Autowired
private MessageListener listener;

@PostConstruct
public void subscribe() {
    
    
    container.addMessageListener(listener, new PatternTopic("news.*"));
}
  1. アナウンスをする:
@Autowired
private RedisTemplate<String, Object> redisTemplate;

public void publish() {
    
    
    redisTemplate.convertAndSend("news.world", "Hello, world!");
}

Redis パブリッシュ/サブスクライブ モードを使用する場合、システムの信頼性とパフォーマンスを確保するには、サブスクライバーの同時処理能力、メッセージのシリアル化と逆シリアル化などの問題を考慮する必要があります。

3. Redis の入門から熟練度までの一連の記事

「Redisの入門から習熟まで【上級編】:永続AOFの詳細説明」
「Redisの入門から習熟まで【上級編】:永続RDBの詳細説明」
「Redisの入門から習熟まで【上級編】:基礎となるデータ構造辞書(辞書)」詳細解説』
『Redisの入門から習熟まで【上級記事】基礎となるデータ構造の詳しい解説 QuickList』 『
Redisの入門から習熟まで【上級記事】基礎となるデータ構造の詳しい解説 Simple Dynamic String (SDS)』 『
Redis入門から習熟まで【上級編】基盤となるデータ構造圧縮リスト(ZipList)の詳細解説」 「
Redis入門から習熟まで【上級編】データ型Streamの詳細解説と使用例」

おすすめ

転載: blog.csdn.net/wangshuai6707/article/details/131520851