2015-01-02 13 views
28

Câu hỏi chung của tôi là: Sử dụng Redis cho PubSub, điều gì xảy ra với thông báo khi nhà xuất bản đẩy tin nhắn vào kênh nhanh hơn người đăng ký có thể đọc chúng?Redis Pubsub và Message Queuing

Ví dụ, giả sử tôi có:

  • Một đơn giản thông điệp xuất bản xuất bản ở mức 2 msg/giây.
  • Một thuê bao đơn giản đọc tin nhắn với tốc độ 1 msg/giây.

Giả thiết ngây thơ của tôi sẽ là người đăng ký sẽ chỉ thấy 50% tin nhắn được xuất bản lên Redis. Để kiểm tra giả thuyết này, tôi đã viết hai kịch bản:

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) 

Kết quả

  • Khi tôi chạy sub.py đầu tiên, ngay lập tức theo sau pub.py, tôi thấy rằng sub.py thực sự hiển thị tất cả các tin nhắn (1-10), cái khác với độ trễ 1 giây ở giữa. Giả định ban đầu của tôi là sai, Redis đang xếp hàng. Cần kiểm tra thêm.
  • Khi tôi chạy pub.py trước, sau đó đợi 5 giây trước khi chạy sub.py, tôi thấy rằng sub.py chỉ hiển thị nửa sau của thư (5-10). Tôi đã có thể giả định này ban đầu, nhưng với kết quả trước đây của tôi, tôi sẽ có tin nhắn suy nghĩ được xếp hàng đợi, dẫn tôi đến kết luận sau đây ...

Kết luận

  • Redis máy chủ dường như thông điệp xếp hàng cho từng khách hàng, cho mỗi kênh.
  • Miễn là khách hàng đang nghe, việc đọc tin nhắn không quan trọng đến mức nào. Miễn là nó được kết nối, tin nhắn sẽ vẫn được xếp hàng đợi cho khách hàng đó, cho kênh đó.

Câu hỏi còn lại

  • Là những kết luận hợp lệ?
  • Nếu có, thông báo khách hàng/kênh sẽ vẫn được xếp hàng trong bao lâu?
  • Nếu có, có một lệnh redis-cli info để xem có bao nhiêu thư được xếp hàng đợi (cho mỗi khách hàng/kênh) không?

Trả lời

52

Các thử nghiệm là hợp lệ, nhưng kết luận là một phần sai.

Redis không xếp hàng bất kỳ thứ gì trên các kênh pub/sub.Ngược lại, nó có xu hướng đọc mục từ socket của nhà xuất bản, và viết mục trong tất cả các socket thuê bao, lý tưởng là trong cùng một vòng lặp của vòng lặp sự kiện. Không có gì được lưu giữ trong cấu trúc dữ liệu Redis.

Bây giờ, như bạn đã chứng minh, vẫn còn một số loại đệm. Đó là do việc sử dụng các ổ cắm TCP/IP và bộ đệm truyền thông Redis.

Ổ cắm có bộ đệm và tất nhiên, TCP đi kèm với một số cơ chế kiểm soát luồng. Nó tránh mất dữ liệu khi bộ đệm đầy. Nếu thuê bao không đủ nhanh, dữ liệu sẽ tích lũy trong bộ đệm ổ cắm của nó. Khi đã đầy, TCP sẽ chặn giao tiếp và ngăn Redis đẩy thêm thông tin vào ổ cắm.

Redis cũng quản lý bộ đệm giao tiếp đầu ra (trên đầu trang của các ổ cắm) để tạo dữ liệu được định dạng bằng giao thức Redis. Vì vậy, khi bộ đệm đầu ra của ổ cắm đầy, vòng lặp sự kiện sẽ đánh dấu các ổ cắm là không thể ghi, và dữ liệu sẽ vẫn còn trong bộ đệm đầu ra Redis.

Cung cấp kết nối TCP vẫn hợp lệ, dữ liệu có thể vẫn còn trong bộ đệm trong một thời gian rất dài. Bây giờ, cả bộ đệm đầu ra socket và Redis đều bị ràng buộc. Nếu các thuê bao thực sự quá chậm, và rất nhiều dữ liệu tích lũy, Redis cuối cùng sẽ đóng kết nối với các thuê bao (như một cơ chế an toàn).

Theo mặc định, đối với pub/sub, Redis có giới hạn mềm là 8 MB và giới hạn cứng là 32 MB cho mỗi bộ đệm kết nối. Nếu bộ đệm đầu ra đạt đến giới hạn cứng, hoặc nếu nó nằm giữa giới hạn mềm và cứng trong hơn 60 giây, kết nối với thuê bao chậm sẽ bị đóng.

Biết số lượng thư đang chờ xử lý không dễ dàng. Nó có thể được đánh giá bằng cách xem kích thước của thông tin đang chờ xử lý trong bộ đệm ổ cắm và bộ đệm đầu ra Redis.

Đối với bộ đệm đầu ra Redis, bạn có thể sử dụng CLIENT LIST command (từ redis-cli). Kích thước của bộ đệm đầu ra được trả về trong các trường obl và oll (tính theo byte).

Đối với bộ đệm ổ cắm, không có lệnh Redis. Tuy nhiên, trên Linux, có thể xây dựng một kịch bản để giải thích nội dung của tệp/proc/net/tcp. Xem ví dụ here. Kịch bản này có thể cần phải được điều chỉnh cho hệ thống của bạn.

+0

"Có câu trả lời mới cho câu hỏi - nhấp vào _đây_ để tải câu hỏi" - bạn nhập nhanh hơn tôi và đưa ra câu trả lời tuyệt vời :) –

+3

Xin lỗi :-) Tôi được thúc đẩy bởi câu hỏi! –

+0

Câu trả lời rất hay! Có thể vô hiệu hóa bộ đệm Redis hoàn toàn và chỉ nhận dữ liệu thực tế trên sự kiện mới (ví dụ: cập nhật thị trường chứng khoán) ngay cả khi mất dữ liệu trước đó để đảm bảo dữ liệu được cập nhật nhất? –

Các vấn đề liên quan