Làm thế nào để thực hiện một hàng đợi tin nhắn trên Redis?


29

Tại sao Redis cho xếp hàng?

Tôi có ấn tượng rằng Redis có thể là một ứng cử viên tốt để thực hiện một hệ thống xếp hàng. Cho đến thời điểm này, chúng tôi đã sử dụng cơ sở dữ liệu MySQL của chúng tôi với bỏ phiếu hoặc RabbitMQ. Với RabbitMQ, chúng tôi đã gặp nhiều vấn đề - các thư viện máy khách rất kém và có lỗi và chúng tôi không muốn đầu tư quá nhiều giờ của nhà phát triển để sửa chúng, một vài vấn đề với bảng điều khiển quản lý máy chủ, v.v. ít nhất, chúng ta không nắm bắt được mili giây hoặc hiệu suất đẩy nghiêm trọng, miễn là một hệ thống có kiến ​​trúc hỗ trợ hàng đợi một cách thông minh, có lẽ chúng ta đang ở trong tình trạng tốt.

Được rồi, đó là nền tảng. Về cơ bản, tôi có một mô hình xếp hàng đơn giản, rất cổ điển - một số nhà sản xuất sản xuất công việc và một số người tiêu dùng tiêu thụ công việc, và cả nhà sản xuất và người tiêu dùng cần có khả năng mở rộng quy mô một cách thông minh. Hóa ra một người ngây thơ PUBSUBkhông làm việc, vì tôi không muốn tất cả người đăng ký tiêu thụ công việc, tôi chỉ muốn một người đăng ký nhận công việc. Ở lần đầu tiên, có vẻ như tôi BRPOPLPUSHlà một thiết kế thông minh.

Chúng ta có thể sử dụng BRPOPLPUSH không?

Thiết kế cơ bản với BRPOPLPUSHlà bạn có một hàng đợi công việc và hàng đợi tiến độ. Khi một người tiêu dùng nhận được công việc, nó sẽ đẩy vật phẩm vào hàng đợi tiến độ và khi nó hoàn thành công việc thì đó LREMlà nó. Điều này ngăn chặn việc làm đen nếu khách hàng chết và khiến việc giám sát trở nên khá dễ dàng - ví dụ chúng ta có thể biết liệu có vấn đề gì khiến người tiêu dùng mất nhiều thời gian để thực hiện các nhiệm vụ hay không, ngoài việc cho biết nếu có khối lượng lớn nhiệm vụ.

Nó đảm bảo

  • công việc được giao cho chính xác một người tiêu dùng
  • làm việc trong một hàng đợi tiến bộ, vì vậy nó không thể là lỗ đen nếu người tiêu dùng

Hạn chế

  • Nó có vẻ khá lạ đối với tôi rằng thiết kế tốt nhất mà tôi tìm thấy không thực sự sử dụng PUBSUBvì đây dường như là những gì hầu hết các bài đăng trên blog về việc xếp hàng trên Redis tập trung vào. Vì vậy, tôi cảm thấy như tôi đang thiếu một cái gì đó rõ ràng. Cách duy nhất tôi thấy để sử dụng PUBSUBmà không tiêu thụ các tác vụ hai lần là chỉ cần đẩy một thông báo rằng công việc đã đến, mà người tiêu dùng sau đó có thể không chặn-ly RPOPLPUSH.
  • Không thể yêu cầu nhiều hơn một mục công việc tại một thời điểm, đây dường như là một vấn đề về hiệu suất. Không phải là một vấn đề lớn đối với tình huống của chúng tôi, nhưng rõ ràng là hoạt động này không được thiết kế cho thông lượng cao hoặc tình huống này
  • Tóm lại: tôi có thiếu điều gì ngu ngốc không?

Đồng thời thêm thẻ node.js, vì đó là ngôn ngữ mà tôi chủ yếu xử lý. Node có thể cung cấp một số đơn giản hóa trong việc triển khai, do tính chất đơn luồng và không chặn của nó, nhưng hơn nữa tôi đang sử dụng thư viện nút-redis và các giải pháp cũng nên hoặc có thể nhạy cảm với các điểm mạnh và điểm yếu của nó.

Câu trả lời:


5

Nếu bạn muốn sử dụng Redis cho hàng đợi tin nhắn trong Node.js và bạn không phiền khi sử dụng mô-đun cho điều đó thì bạn có thể thử RSMQ - Hàng đợi tin nhắn đơn giản Redis cho Node. Nó không có sẵn tại thời điểm câu hỏi này được hỏi nhưng hôm nay nó là một lựa chọn khả thi.

Nếu bạn thực sự muốn tự thực hiện hàng đợi như bạn đã nêu trong câu hỏi của mình thì bạn có thể muốn đọc nguồn RSMQ vì đó chỉ là 20 màn hình mã thực hiện chính xác những gì bạn đang yêu cầu.

Xem:


Tôi sẽ chấp nhận điều này trừ khi sau này tôi biết nó thực sự thiếu sót hoặc bị hỏng hoặc một cái gì đó.
djechlin

22

Tôi đã gặp một số khó khăn cho đến nay tôi muốn ghi lại ở đây.

Làm thế nào để bạn xử lý logic kết nối lại?

Đây là một vấn đề khó khăn và một vấn đề đặc biệt khó khăn trong việc thiết kế và thực hiện hàng đợi tin nhắn. Tin nhắn phải có khả năng xếp hàng ở đâu đó khi người tiêu dùng ngoại tuyến, do đó, một pub-sub đơn giản không đủ mạnh và người tiêu dùng cần kết nối lại trong trạng thái nghe. Chặn pops là trạng thái khó duy trì, bởi vì chúng là trạng thái nghe không bình thường . Lắng nghe phải là một hoạt động bình thường, nhưng khi xử lý ngắt kết nối đối với một cửa sổ chặn, bạn có niềm vui suy nghĩ rất kỹ về việc ngắt kết nối xảy ra ngay sau khi hoạt động thành công hay ngay trước khi hoạt động thất bại. Điều này không phải là không thể vượt qua, nhưng nó không mong muốn.

Hơn nữa, hoạt động nghe nên đơn giản nhất có thể. Lý tưởng nhất là phải có các tính chất sau:

  • Lắng nghe là bình thường.
  • Người tiêu dùng luôn lắng nghe và logic điều tiết được xử lý bên ngoài mã logic nghe. RabbitMQ gói gọn điều này bằng cách cho phép người tiêu dùng ràng buộc số lượng tin nhắn chưa được đóng gói có thể có.
    Đặc biệt, tôi đã đi với một thiết kế kém trong đó việc nhập lại một cửa sổ chặn chặn phụ thuộc vào sự thành công của các hoạt động trước đó, vốn dễ vỡ và đòi hỏi phải suy nghĩ kỹ.

Tôi hiện đang ủng hộ giải pháp Redis PUBSUB + RPOPLPUSH. Điều này tách riêng thông báo công việc từ tiêu thụ công việc, cho phép chúng tôi đưa ra một giải pháp lắng nghe sạch sẽ. PUBSUB chỉ chịu trách nhiệm thông báo công việc. Bản chất nguyên tử của RPOPLPUSH chịu trách nhiệm tiêu thụ và ủy thác công việc cho chính xác một người tiêu dùng. Lúc đầu, giải pháp này có vẻ phức tạp không cần thiết so với một cửa sổ chặn, nhưng bây giờ tôi thấy rằng sự phức tạp không hề cần thiết; nó đã giải quyết một vấn đề khó khăn

Tuy nhiên, giải pháp này không tầm thường:

  • Người tiêu dùng cũng nên kiểm tra công việc trên kết nối lại.
  • Người tiêu dùng có thể muốn thực hiện một cuộc thăm dò cho công việc mới dù sao, để dự phòng. Nếu cuộc thăm dò thực sự thành công, một cảnh báo nên được phát ra, vì điều này chỉ xảy ra giữa mức tiêu thụ trên PUBSUB và cuộc thăm dò trên RPOPLPUSH. Do đó, nhiều cuộc thăm dò thành công cho thấy một hệ thống thuê bao bị hỏng.

Lưu ý rằng thiết kế PUBSUB / RPOPLPUSH cũng có vấn đề mở rộng. Mỗi người tiêu dùng nhận được một thông báo nhẹ về mọi tin nhắn, điều đó có nghĩa là điều này có một tắc nghẽn không cần thiết. Tôi nghi ngờ có thể sử dụng các kênh để phân chia công việc nhưng đây có lẽ là một thiết kế phức tạp để làm việc tốt.


Không chắc chắn tôi theo dõi vấn đề với việc chặn người tiêu dùng. Đối với tôi, dường như nếu không có công việc xử lý thì người tiêu dùng nên chặn cho đến khi có một số, mặc dù tôi cho rằng nếu người tiêu dùng cũng đang làm những việc khác có thể là một câu chuyện khác, nhưng đó không phải là vấn đề trong ứng dụng và không quá nhiều cho hàng đợi? IE sẽ không chặn một luồng trong một ứng dụng lớn hơn là một giải pháp thanh lịch hơn, khi đó luồng có thể thông báo cho ứng dụng khi nó đã lấy một công việc từ hàng đợi. Có lẽ nó chỉ là việc sử dụng nút đang tạo ra sự phức tạp.
AaronM

9
Tôi tò mò về việc bạn đã đi được bao xa kể từ tháng 8 năm ngoái. Bạn có thể giải quyết vấn đề của bạn để bạn hài lòng không? Làm thế nào bạn giải quyết chúng?
AaronM

3
AAA: giống như @AaronM Tôi rất thích nghe bạn đã tiến bộ như thế nào.
bjornl

Đã đồng ý. Làm thế nào điều này đã tiến triển? Tôi thích ý tưởng loại bỏ RabbitMQ khỏi ngăn xếp và sử dụng Redis dù sao đi nữa. Vấn đề của tôi là làm thế nào để đăng ký một người tiêu dùng bằng RSMQ (nút lib).
ra9r

@raiglstorfer đã không làm việc ở đó trong hai năm: P hãy thoải mái nghiên cứu và đăng ...
djechlin

0

Vì vậy, lý do lớn nhất để chọn sử dụng RabbitMQ so với Redis là các tình huống thất bại và phân cụm.

Bài viết này thực sự giải thích nó tốt nhất, vì vậy tôi sẽ chỉ cung cấp liên kết:

https://aphyr.com/posts/283-jepsen-redis

Redis sentinel và gần đây là redis clustering không thể xử lý một số tình huống lỗi rất cơ bản khiến nó trở thành một lựa chọn tồi cho hàng đợi.

RabbitMQ có bộ vấn đề riêng của mình, tuy nhiên, người ta nói rằng nó rất chắc chắn trong sản xuất và là một hàng đợi tin nhắn tốt.

Đây là bài viết cho thỏ:

https://aphyr.com/posts/315-jepsen-rabbitmq

Khi bạn xem xét lý thuyết CAP (tính nhất quán, tính sẵn có và xử lý phân vùng), bạn chỉ có thể chọn 2 trên 3. Chúng tôi đang tận dụng RMQ cho CP (xử lý nhất quán và phân vùng) với tải thông điệp của chúng tôi, nếu chúng tôi không có sẵn, thì đó không phải là ' ngày tận thế. Để không bị mất tin nhắn, chúng tôi sử dụng bỏ qua cho việc xử lý phân vùng để không bị mất tin nhắn. Các bản sao có thể được xử lý do nguồn quản lý UUID.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.