복붙노트

[REDIS] 어떻게 BookSleeve / 레디 스에서 PubSub 작동합니까?

REDIS

어떻게 BookSleeve / 레디 스에서 PubSub 작동합니까?

나는 가장 좋은 방법은 게시하고 BookSleeve을 사용하여 채널에 가입 무엇인지 궁금합니다. 나는 현재 여러 정적 방법 (아래 참조) 개인 정적 사전 <문자열, RedisSubscriberConnection> subscribedChannels에 저장되는 날 새로 만든 채널을 특정 채널에 콘텐츠를 게시 할 수 있도록하는 구현 ;.

내가 채널을 게시하고 같은 응용 프로그램 내 채널에 가입하고자 할 주어진이 올바른 접근 방법이다 (참고 : 내 래퍼는 정적 클래스입니다). 심지어 내가 게시하고 구독 할 하나 개의 채널을 생성하기에 충분한가요? 분명히 나는 ​​같은 응용 프로그램 내에서 가입하는 것보다 같은 채널에 게시하지 않습니다. 그러나 나는 그것을 테스트하고 일했다 :

 RedisClient.SubscribeToChannel("Test").Wait();
 RedisClient.Publish("Test", "Test Message");

그것은했다.

내 질문에 여기 :

전용 채널을 게시하고 전용이 모두 하나 개의 채널을 사용하는 것보다 채널을 오히려 구독 1)은 설정에보다 효율적으로 수 있습니까?

2) "채널"및 의미 "PatternSubscription"의 차이점은 무엇입니까? 나의 이해는 내가 올바른, 동일한 채널에 PatternSubscription ()를 통해 여러 '주제'에 가입 할 수 있다는 것입니다? 나는 각 "항목"에 대한 호출 다른 콜백을 갖고 싶어하지만 설정에 올바른 각 주제에 대한 채널을 가질 것인가? 즉, 효율적인하거나 그 무리를 줄까요?

코드 조각 여기.

감사!!!

    public static Task<long> Publish(string channel, byte[] message)
    {
        return connection.Publish(channel, message);
    }

    public static Task SubscribeToChannel(string channelName)
    {
        string subscriptionString = ChannelSubscriptionString(channelName);

        RedisSubscriberConnection channel = connection.GetOpenSubscriberChannel();

        subscribedChannels[subscriptionString] = channel;

        return channel.PatternSubscribe(subscriptionString, OnSubscribedChannelMessage);
    }

    public static Task UnsubscribeFromChannel(string channelName)
    {
        string subscriptionString = ChannelSubscriptionString(channelName);

        if (subscribedChannels.Keys.Contains(subscriptionString))
        {
            RedisSubscriberConnection channel = subscribedChannels[subscriptionString];

            Task  task = channel.PatternUnsubscribe(subscriptionString);

            //remove channel subscription
            channel.Close(true);
            subscribedChannels.Remove(subscriptionString);

            return task;
        }
        else
        {
            return null;
        }
    }

    private static string ChannelSubscriptionString(string channelName)
    {
        return channelName + "*";
    }

해결법

  1. ==============================

    1.1 : 예 (시험)에 하나 개의 채널이있다; 채널은 특정 술집 / 하위 교환에 사용되는 이름입니다. 그것은, 그러나, 필요한 때문에이 API의 작품을 레디 스 방법의 세부 사항에이 연결을 사용하는 것입니다. 를 제외하고 다른 작업을 수행 할 수있는 구독이있는 연결 :

    1 : 예 (시험)에 하나 개의 채널이있다; 채널은 특정 술집 / 하위 교환에 사용되는 이름입니다. 그것은, 그러나, 필요한 때문에이 API의 작품을 레디 스 방법의 세부 사항에이 연결을 사용하는 것입니다. 를 제외하고 다른 작업을 수행 할 수있는 구독이있는 연결 :

    그러나, 나는이 이해가 안 :

    private static Dictionary<string, RedisSubscriberConnection>
    

    당신이 당신에게 뭔가 특별한 음식을 장만이 아니라면 당신은 하나 명 이상의 가입자 접속을 필요가 없습니다. 하나의 가입자 접속 구독의 임의의 수를 처리 할 수 ​​있습니다. 빠른 내 서버 중 하나에 클라이언트 목록 확인, 나는 (글을 쓰는 시점에서)와 하나 개의 연결 23002 개 구독 있습니다. 어느 아마 감소하지만, 수 : 그것은 작동합니다.

    2 : 가입 패턴은 와일드 카드를 지원; 그래서 대신에 / 주제 구독 이상 / 1 / 주제 / 2 / 등 당신이 / 주제 / * 구독 할 수 있습니다. 제작에서 사용되는 실제 채널의 이름은 콜백 서명의 일부로서, 수신기에 제공된다.

    어느 작업 할 수 있습니다. 게시의 성능이 독특한 구독의 총 수의 영향을 주목해야한다 -하지만 솔직히이 (같이 : 에선 0ms) 여전히 바보 빨리 당신이 psubscribe보다는 구독하여 구독 채널의 여러 수만이 경우에도 마찬가지입니다.

    그러나에서하는 게시

    나는 술집 / 하위의 레디 스 설명서를 읽어 보시기 바랍니다.

    질문에 다음과 편집 :

    그 모두에서 차이를하지 않습니다; 당신이 결과 / 대기 ()을 언급 이후, 나는 당신에게 BookSleeve하려고합니다 이야기 가정 -이 경우 멀티플렉서가 이미 명령 순서를 유지합니다. 자체는 단일 스레드이며, 항상 순서대로 단일 연결에서 명령을 처리 할 레디 스. 그러나 : 가입자의 콜백은 비동기 적으로 수행 될 수 있으며, 작업자 스레드 (별도) 손으로 할 수있다. 나는 현재 내가에 주문 RedisSubscriberConnection에서 수 있도록이 강제 할 수 있는지 여부를 조사하고있다.

    업데이트 : 1.3.22은 이후 당신이 PreserveOrder에 CompletionMode을 설정할 수 있습니다에서 - 모든 콜백이 순차적이 아니라 동시에보다는 완료됩니다.

    첫째, 그 때 높은 소리 - 로컬 테스트 I 얻을 1766ms (로컬) 또는 1219ms (원격) (즉, 힘 사운드 직관,하지만 내 "로컬"ISN '(10 만 그들 모두에 대한 응답을 기다리는 포함한 출판물에 대한) 레디 스의 동일한 버전을 실행 t; 내 "원격"를 CentOS에서 2.6.12입니다 내 "로컬"입니다 2.6.8-PRE2 Windows에서).

    나는 빨리 실제 서버를 만들거나 네트워크 속도를 높일 수는 없지만 : 경우에이 (당신을 위해), 내가 추가 한 패킷 단편화 SuspendFlush () / ResumeFlush () 쌍입니다. 이 비활성화 열망 플러시 (즉, 송신 큐가 비어있을 때, 일이 여전히 플러싱 다른 종류의); 당신이 도움이 찾을 수 있습니다 :

    conn.SuspendFlush();
    try {
        // start lots of operations...
    } finally {
        conn.ResumeFlush();
    }
    

    당신이 재개 될 때까지 당신이 ResumeFlush를 호출 할 때까지 () 송신 버퍼에 여전히 일부 작업이있을 수 있기 때문에 당신이 잠깐 안됩니다. 대신에 모든으로, 나는 (100,000 작업에 대해) 수 :

    local: 1766ms (eager-flush) vs 1554ms (suspend-flush)
    remote: 1219ms (eager-flush) vs 796ms (suspend-flush)
    

    당신이 볼 수 있듯이이 네트워크를 통해 적은 수의 패킷을 두는 것, 그것은 원격 서버에 더 도움이됩니다.

    최근 CreateBatch도 추가되었는지하지만 참고 - 그 위에 의해 해결된다 생각합니다. 트랜잭션없이 : 단지 - 일괄 트랜잭션처럼 많이 운영하고 있습니다. 다시, 패킷 단편화를 줄이기위한 또 다른 메커니즘입니다. 특정 경우에, 나는이 (플러시에) / 이력서를 중단 의심 당신의 최선의 방법이다.

    만큼 당신이 차단 작업 (blpop, brpop, brpoplpush 등)을 수행하거나 선 아래로 대형에 BLOB을 붙이려는 건 아니죠으로 (이 지워 동안 잠재적으로 다른 작업을 지연), 각 유형의 단일 연결은 일반적으로 아주 잘 작동합니다. 하지만 YMMV은 정확한 사용 요구 사항에 따라.

  2. from https://stackoverflow.com/questions/15862534/how-does-pubsub-work-in-booksleeve-redis by cc-by-sa and MIT license