2015-01-02 29 views
28

私の全体的な質問です:PubSubのためのRedisを使用して、出版社が速く、加入者がそれらを読むことができるよりもチャネルにメッセージをプッシュするときにメッセージに何が起こりますか?例えばRedisのPubSubのメッセージキュー

、のは、私が持っているとしましょう:

  • 2 MSG /秒の速度でメッセージを公開シンプルな出版社。
  • 1つのMSG /秒の速度でメッセージを読む簡単加入。

私の前提は、サブスクライバはRedisに公開されたメッセージの50%しか見ることができないということです。

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) 

結果

  • 私は走った:この理論をテストするために、私は2つのスクリプトを書きましたsub.pyまず、直ちにpub.py続いて、私はsub.pyが実際にすべてのメッセージ(1-10)との間に1秒の遅延で次々に表示することを見出しました。私の初期の仮定は間違っていた、Redisはメッセージをキューに入れている。より多くのテストが必要です。
  • 最初にpub.pyを実行してから、sub.pyを実行する前に5秒待ってから、sub.pyにはメッセージの後半(5-10)しか表示されませんでした。私はもともとこれを想定しているだろうが、私の以前の結果を考えると、私は

    • のRedisサーバがに表示されます

    結論...以下の結論に私を導いた、メッセージがキューに入れられたと思っているだろう各クライアントのキューメッセージを各チャネルごとに格納します。

  • 限り、クライアントが待機しているとして、メッセージを読み込むスピードは重要ではありません。接続されている限り、そのクライアントのメッセージはそのチャネルに対してキューに入れられたままになります。

残りの質問

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

答えて

52

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

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

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

ソケットにはバッファがあり、TCPにはいくつかのフロー制御メカニズムが付属しています。バッファがいっぱいになるとデータが失われるのを防ぎます。加入者の速度が十分でない場合、データはソケットバッファに蓄積されます。一杯になると、TCPは通信をブロックし、Redisがソケット内でより多くの情報をプッシュするのを防ぎます。

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

TCP接続が有効な場合、データは非常に長い時間バッファに残る可能性があります。これで、ソケットとRedis出力バッファの両方がバインドされます。加入者が本当に遅すぎると多くのデータが蓄積された場合、Redisは加入者との接続を最終的に閉鎖します(安全機構として)。

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

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

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

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

+0

「質問を読むために新しい答えがあります - それをロードするにはここをクリックしてください」 - あなたは私より速く入力し、すばらしい答えを出しました:) –

+3

申し訳ありません:-)私は疑問に動機づけられました! –

+0

非常に良い答え!レディスバッファを完全に無効にし、データが最新のものであることを確実にするために以前のデータをある程度失ったとしても、新しいイベント(例えば証券取引所市場の更新)でのみ実際のデータのみを受け取ることは可能ですか? –

関連する問題