Soru Redis Pubsub ve Message Queuing


Genel sorum şu: RedS for PubSub'u kullanarak, yayıncılar aboneleri okuyabilenlerden daha hızlı bir kanala mesaj gönderdiğinde mesajlara ne olur?

Örneğin, sahip olduğumu varsayalım:

  • Mesajları 2 msg / sn hızında yayınlayan basit bir yayıncı.
  • Basit bir abone 1 msg / sn hızında mesaj okuyor.

Benim naif varsayım, abonenin Redis'e yayınlanan mesajların sadece% 50'sini görmesi olurdu. Bu teoriyi test etmek için iki senaryo yazdım:

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)

Sonuçlar

  • Koştuğumda sub.py önce, hemen ardından pub.py, Onu buldum sub.py aslında tüm mesajları (1-10), birbiri ardına 1 saniye gecikmeli olarak görüntüler. İlk varsayım yanlıştı, Redis mesajları sıraya sokuyor. Daha fazla test gerekli.
  • Koştuğumda pub.py önce, sonra çalıştırmadan önce 5 saniye bekledim sub.py, Onu buldum sub.py sadece mesajların ikinci yarısını görüntüledi (5-10). İlk başta bunu kabul ederdim, ama önceki sonuçlarıma bakılırsa, mesajların sıraya konmuş olacağını düşünmüştüm, ki bu da beni şu sonuca götürdü ...

Sonuçlar

  • Redis sunucusu, her bir kanal için her bir istemci için mesajları sıraya koyar.
  • Bir müşteri dinlediğinde, mesajların ne kadar hızlı okunduğunun önemi yoktur. Bağlandığı sürece, mesaj o istemci için o kanal için kuyruğa girer.

Kalan Sorular

  • Bu sonuçlar geçerli mi?
  • Eğer öyleyse, müşteri / kanal mesajları ne kadar süre bekletildi?
  • Eğer öyleyse, orada bir redis-cli info kaç mesajın kuyruklandığını görmek için komut (her bir istemci / kanal için)?

32
2018-01-02 17:13


Menşei




Cevaplar:


Testler geçerlidir, ancak sonuçlar kısmen yanlıştır.

Redis, pub / alt kanallarda hiçbir şey sıraya almaz. Aksine, öğeyi yayıncı soketinden okuma eğilimindedir ve öğeyi tüm abone soketlerine, ideal olarak olay döngüsünün aynı yinelemesine yazar. Redis veri yapılarında hiçbir şey tutulmaz.

Şimdi, gösterdiğiniz gibi, hala bir çeşit tamponlama var. TCP / IP soketlerinin ve Redis iletişim tamponlarının kullanılmasından kaynaklanmaktadır.

Soketlerin tamponları vardır ve elbette TCP bazı akış kontrol mekanizmaları ile gelir. Tampon doluyken veri kaybını önler. Bir abone yeterince hızlı değilse, veri soket arabelleğinde birikir. Tamamlandığında, TCP iletişimi engeller ve Redis'in sokette daha fazla bilgi itmesini engeller.

Redis ayrıca, Redis protokolü ile formatlanmış verileri oluşturmak için çıkış haberleşme arabelleklerini (soketlerin üstünde) yönetir. Soketin çıktı tamponu dolduğunda, olay döngüsü soketi yazılabilir olarak işaretler ve veriler Redis çıkış tamponlarında kalır.

TCP bağlantısının hala geçerli olması şartıyla, veriler çok uzun süre tamponlarda kalabilir. Şimdi, hem soket hem de Redis çıkış tamponu bağlı. Aboneler gerçekten çok yavaşsa ve bir çok veri birikirse, Redis en sonunda abonelerle olan bağlantıyı (bir güvenlik mekanizması olarak) kapatacaktır.

Varsayılan olarak, pub / sub için Redis, 8 MB'lık bir yazılım sınırına ve bağlantı arabelleği başına 32 MB'lık bir sabit sınıra sahiptir. Çıkış tamponu sabit limite ulaşırsa veya 60 saniyeden uzun bir süre yumuşak ve sert sınırlar arasında kalırsa, yavaş abone ile bağlantı kapatılır.

Bekleyen mesajların sayısını bilmek kolay değildir. Soket tamponlarında bekleyen bilgilerin büyüklüğüne ve Redis çıkış tamponlarına bakarak değerlendirilebilir.

Redis çıkış arabellekleri için MÜŞTERİ LİSTESİ (redis-cli'den). Çıkış arabelleğinin boyutu, obl ve oll alanlarında (bayt cinsinden) döndürülür.

Soket tamponları için Redis komutu yoktur. Ancak, Linux'ta / proc / net / tcp dosyasının içeriğini yorumlamak için bir betik oluşturmak mümkündür. Bir örneğe bakın İşte. Bu betiğin muhtemelen sisteminize uyarlanması gerekiyor.


56
2018-01-02 18:23



"Soru için yeni cevaplar var - tıkla İşte onları yüklemek için "- sen benden daha hızlı yaz ve inanılmaz bir cevap verdi :) - Itamar Haber
Üzgünüm :-) Ben soru ile motive oldu! - Didier Spezia
Çok iyi cevap! Redis arabelleklerini tamamen devre dışı bırakmak ve verilerin en güncel olduğundan emin olmak için sadece önceki verilerden bir miktar kayıp olsa bile yalnızca yeni olayda (örneğin borsa piyasası güncellemesi) yalnızca asıl verileri almak mümkün mü? - icherevkov
Hayır, bu mümkün değil. Tampondaki içerik zaten Redis protokolünde kodlanmıştır ve rastgele yerlerde rasgele kesilemez. Büyük olasılıkla tamponun içeriğini yeniden değerlendirmeyi gerektirir. - Didier Spezia
@Didier Spezia, Redis 4.0.7'deki "C" kaynak kodu dosyası, 1) TCP'nin iletişimi engelleyeceği ve Redis'in sokette daha fazla bilgi almasını engelleyeceği 1) kontrol mantığını içerir. 2) Redis aboneler gerçekten çok yavaşsa ve çok fazla veri biriktiriyorsa abonelerle bağlantıyı sonlandıracak mı? Teşekkür ederim. - Frank