5

Redis は PUBSUB をサポートしています。購読はとても簡単です:

redis 127.0.0.1:6379> subscribe foo
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "foo"
3) (integer) 1

ただし、サブスクライブ中はサーバーがコマンドを受け付けないため、サブスクライブを解除することはできないようです。たとえば、redis-cliredis に同梱されているクライアントでは、制御がクライアントに返されないため、入力unsubscribeしてもどこにも行きません。

これは、ドキュメント、関数、または PEBKAC の問題の明らかなエラーのようです。何を与える?

バージョン:

$ ./redis-server --version
Redis サーバー v=2.6.14 sha=00000000:0 malloc=libc ビット=64

4

3 に答える 3

6

クライアントとは、ここにあるクライアントのリストを意味すると思います。

http://redis.io/clients

Hiredis クライアントを使用したことのある人として、私はこの推奨事項を次のように推測します。

クライアントがサブスクライブ状態に入ると、追加の SUBSCRIBE、PSUBSCRIBE、UNSUBSCRIBE、および PUNSUBSCRIBE コマンドを除いて、他のコマンドを発行することは想定されていません。

このページ: http://redis.io/commands/subscribeは、それらのクライアントにのみ適用されます。

redis-cli はそれらのクライアントの 1 つです。したがって、コメントは redis-cli のユーザーへの指示ではありません。

代わりに、redis-cli はバス上でメッセージを待機することをブロックします (ctrl+c を介してのみ登録解除されます)。

別のクライアントを使用する場合 (より具体的には、別のクライアントを実装している場合)、サブスクライブ状態になるようにその規則を遵守する必要があると思います (ただし、クライアントは必ずしもそうではありません)。ブロッキング)。

それを明確にするために、ドキュメントをもう少し明確にすることができると思います。ただし、ドキュメントはサーバー自体にあり、redis-cli アプリケーションにはありません。ただし、ドキュメント リポジトリで調整を行い、プル リクエストを送信することはできます。

https://github.com/antirez/redis-doc/blob/master/commands/subscribe.md

于 2013-07-12T18:26:12.223 に答える
0
An example of publishing subscribing and unsubscribing in c++.




#include <signal.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <hiredis/hiredis.h>
#include <hiredis/async.h>
#include <hiredis/adapters/libevent.h>
#include <boost/thread/thread.hpp>

using namespace std;

struct event_base* base;
std::string CHANNEL("");


void subCallback(redisAsyncContext *c, void *r, void *privdata) ;

void unSubscribe(redisAsyncContext* _redisContext){

  std::string input;

  while(1)
  {
    cin>>input;
    if(input.compare("unsub") == 0)
      break;
    sleep(5);
  }

  std::string command("unsubscribe ");
  command.append(CHANNEL);

  cout<<
    redisAsyncCommand(_redisContext, 
        subCallback, 
        (char*)"unsub", command.c_str())<<endl; 
}

void subCallback(redisAsyncContext *c, void *r, void *privdata) {

  redisReply *reply = (redisReply*)r;
  if (reply == NULL){
    cout<<"Response not recev"<<endl; 
    return;
  }
  if(reply->type == REDIS_REPLY_ARRAY & reply->elements == 3)
  {
    if(strcmp( reply->element[0]->str,"subscribe") != 0)
    {
      cout<<"Reply for:  "<<reply->element[0]->str<<endl;
      if(strcmp( reply->element[0]->str,"unsubscribe") == 0)
      {
        exit(1);
      }

      cout<<"Message received -> "<<
        reply->element[2]->str<<"( on channel : "<<reply->element[1]->str<<")"<<endl;
    }
  }
}


void pubCallback(redisAsyncContext *c, void *r, void *privdata) {

  redisReply *reply = (redisReply*)r;
  if (reply == NULL){
    cout<<"Response not recev"<<endl; 
    return;
  }
  cout<<"message published"<<endl;
  redisAsyncDisconnect(c);
}

void connectCallback(const redisAsyncContext *c, int status) {
  if (status != REDIS_OK) {
    cout<<"Error in connect: %s\n"<< c->errstr<<endl;
    return;
  }
  cout<<"Connected to redis server..."<<endl;
}

void disconnectCallback(const redisAsyncContext *c, int status) {
  if (status != REDIS_OK) {
    cout<<"Error in disconnect: %s\n"<< c->errstr<<endl;
    return;
  }
  cout<<"Disconnected...\n"<<endl;
}

int main(int argv, char** args)
{
  string processName(args[1]);

  signal(SIGPIPE, SIG_IGN);
//  struct event_base*
    base = event_base_new();

  redisAsyncContext* 
    _redisContext = redisAsyncConnect("10.0.0.30", 6379);

  if (_redisContext->err) {
    /* Let context leak for now... */
    cout<<"Error: "<< _redisContext->errstr<<endl;
    return 1;
  }

  redisLibeventAttach(_redisContext,base);
  //redisAsyncSetConnectCallback(_redisContext,connectCallback);
  //redisAsyncSetDisconnectCallback(_redisContext,disconnectCallback);

  if(processName.compare("pub") == 0)
  {
    string command ("publish ");
    command.append(args[2]);
    command.append (" ");
    command.append(args[3]);

    cout<<
      redisAsyncCommand(_redisContext, 
          pubCallback, 
          (char*)"pub", command.c_str())<<endl; 

  }
  else if(processName.compare("sub") == 0)
  {
    boost::thread unsubscribe(&unSubscribe, _redisContext);

    string command ("subscribe ");
    command.append(args[2]);

    CHANNEL.append(args[2]);

    cout<<
      redisAsyncCommand(_redisContext, 
          subCallback, 
          (char*)"sub", command.c_str())<<endl; 

  }
  else
    cout<<"Try pub or sub"<<endl;

  event_base_dispatch(base);

  return 0;
}

コードを実行して、サブスクリプション、パブリッシュ、およびサブスクライブ解除をテストできます。

  • サブスクライブ: (最初の exe)

    ./pubsub channel1
    
  • パブリッシュ: (2 番目の exe)

    ./pubsub pub channel1 hi
    

    最初のexeで出力

    0

    返信先: メッセージ

    メッセージ受信 -> こんにちは (チャネル: channel1)

  • 最初の exe のサブスクライブを解除し、最初の exe コンソールで unsub と入力します。最終出力:

    0 返信先: メッセージ

    メッセージ受信 -> こんにちは (チャネル: channel1)

    退会

    0

    返信先: 登録解除

于 2013-11-20T07:58:30.587 に答える