73

私の全体的な質問は次のとおりです。PubSub に Redis を使用する場合、サブスクライバーがメッセージを読み取る速度よりもパブリッシャーがメッセージをチャネルにプッシュすると、メッセージはどうなりますか?

たとえば、私が持っているとしましょう:

  • 2 メッセージ/秒の速度でメッセージをパブリッシュする単純なパブリッシャー。
  • 1 msg/sec の速度でメッセージを読み取る単純なサブスクライバー。

私の素朴な仮定は、サブスクライバーは Redis に公開されたメッセージの 50% しか見ることができないということです。この理論をテストするために、次の 2 つのスクリプトを作成しました。

pub.py

queue = redis.StrictRedis(host='localhost', port=6379, db=0)
channel = queue.pubsub()

for i in range(10): 
    queue.publish("test", i)
    time.sleep(0.5)

sub.py

r = redis.StrictRedis(host='localhost', port=6379, db=0)
p = r.pubsub()
p.subscribe('test')

while True:
    message = p.get_message()
    if message:
        print "Subscriber: %s" % message['data']
    time.sleep(1)

結果

  • 最初にを実行したsub.py直後に を実行すると、実際にはすべてのメッセージ (1 ~ 10) が 1 秒間隔で次々に表示されるpub.pyことがわかりました。sub.py私の最初の仮定は間違っていました。Redis はメッセージをキューに入れています。さらにテストが必要です。
  • 最初に実行してからpub.py5 秒待ってから実行すると、メッセージの後半 (5-10) しか表示されないsub.pyことがわかりました。sub.py当初はこれを想定していましたが、以前の結果を考えると、メッセージがキューに入れられていると考えていたため、次の結論に至りました...

結論

  • Redis サーバーは、クライアントごと、チャネルごとにメッセージをキューに入れているように見えます。
  • クライアントがリッスンしている限り、メッセージの読み取り速度は重要ではありません。接続されている限り、メッセージはそのクライアント、そのチャネルのキューに入れられたままになります。

残りの質問

  • これらの結論は有効ですか?
  • その場合、クライアント/チャネル メッセージはどのくらいキューに入れられたままになりますか?
  • もしそうなら、redis-cli info(各クライアント/チャネルごとに)キューに入れられているメッセージの数を確認するコマンドはありますか?
4

1 に答える 1

138

テストは有効ですが、結論は部分的に間違っています。

Redis は、pub/sub チャネルで何もキューに入れません。反対に、パブリッシャー ソケットからアイテムを読み取り、すべてのサブスクライバー ソケットにアイテムを書き込む傾向があります。理想的には、イベント ループの同じ反復でです。Redis データ構造には何も保持されません。

さて、あなたが示したように、まだある種のバッファリングがあります。これは、TCP/IP ソケットと Redis 通信バッファーの使用によるものです。

ソケットにはバッファがあり、もちろん TCP にはいくつかのフロー制御メカニズムが付属しています。バッファがいっぱいになったときにデータが失われるのを防ぎます。サブスクライバの速度が十分でない場合、データはそのソケット バッファに蓄積されます。いっぱいになると、TCP は通信をブロックし、Redis がソケットにそれ以上の情報をプッシュするのを防ぎます。

Redis は、Redis プロトコルでフォーマットされたデータを生成するために、出力通信バッファー (ソケットのバッファーの上) も管理します。そのため、ソケットの出力バッファーがいっぱいになると、イベント ループはソケットを書き込み不可としてマークし、データは Redis 出力バッファーに残ります。

TCP 接続がまだ有効である場合、データは非常に長い間バッファに残る可能性があります。これで、ソケットと Redis 出力バッファーの両方がバインドされました。サブスクライバーが非常に遅く、大量のデータが蓄積された場合、Redis は最終的にサブスクライバーとの接続を閉じます (安全メカニズムとして)。

デフォルトでは、pub/sub の場合、Redis には接続バッファーごとに 8 MB のソフト制限と 32 MB のハード制限があります。出力バッファがハード リミットに達した場合、またはソフト リミットとハード リミットの間に 60 秒以上留まっている場合、低速サブスクライバとの接続は閉じられます。

保留中のメッセージの数を知るのは簡単ではありません。これは、ソケット バッファーと Redis 出力バッファー内の保留情報のサイズを調べることで評価できます。

Redis 出力バッファーの場合、(redis-cli から) CLIENT LIST コマンドを使用できます。出力バッファのサイズは、obl フィールドと oll フィールドに返されます (バイト単位)。

ソケット バッファの場合、Redis コマンドはありません。ただし、Linux では、スクリプトを作成して /proc/net/tcp ファイルの内容を解釈することができます。ここで例を参照してください。このスクリプトは、おそらくシステムに合わせて調整する必要があります。

于 2015-01-02T18:23:24.407 に答える