Giới thiệu về RocketMQ - mu88 mu88 casino

/imgposts/5xul0lyb.jpg

Khi nhắc đến hàng đợi tin nhắn, chắc hẳn những ai đã làm việc với phần backend của web trong một khoảng thời gian đều từng sử dụng qua. Ở công ty trước, tôi đã làm việc với phiên bản cải tiến của NSQ, giống như một phiên bản rút gọn của NOSQL 😐 Thực tế, đó là một hàng đợi tin nhắn được viết bằng ngôn ngữ Go. Mặc dù các bản cập nhật mã nguồn của NSQ không thường xuyên, nhưng nhờ có đội ngũ chuyên trách về middleware tại công ty cũ, nên nó vẫn hoạt động rất tốt. Các chuyên gia trong nhóm này cũng rất tài năng, vì chúng tôi chưa bao giờ gặp phải tình trạng mất tin nhắn nào cả.

Hiện tại, ở công ty hiện tại của tôi, chúng tôi đang sử dụng RocketMQ. Với tư cách là một người mới học, tôi nghĩ rằng việc hiểu rõ hơn về RocketMQ là điều cần thiết, đặc biệt khi hàng đợi tin nhắn là một thành phần quan trọng trong phát triển backend. Tôi tin rằng hầu hết các đội ngũ backend đều cần dùng đến hàng đợi tin nhắn. Trước đây, tôi không thực sự hiểu sâu về nguyên lý hoạt động của NSQ, vậy nên bây giờ tôi muốn tìm hiểu thêm về RocketMQ.

Để giải thích cho những người mới như tôi, hàng đợi tin nhắn được sử dụng để làm gì? Nhiều câu trả lời tiêu chuẩn sẽ nói rằng nó giúp "giảm tải và cân bằng khối lượng công việc". Điều này hoàn toàn đúng, nhưng tôi muốn giải thích theo một kịch bản cụ thể dành cho những bạn cũng là người mới như tôi.

Hãy tưởng tượng một chức năng đặt hàng trên nền tảng thương mại điện tử. Sau khi thanh toán hoàn tất (hoặc thất bại hoặc bị timeout), hệ thống sẽ nhận được phản hồi từ cổng thanh toán. Trong phản hồi này, chúng ta cần thực hiện nhiều tác vụ khác nhau: thay đổi trạng thái đơn hàng, xác nhận phiếu giảm giá, hủy các khoản tiền liên quan, xóa sản phẩm khỏi giỏ hàng, gửi thông báo chăm sóc khách hàng, cập nhật điểm thưởng cho người dùng, v.v.

Nếu tất cả các thao tác này được xử lý trực tiếp trong phản hồi thanh toán, thì yêu cầu về độ ổn định của mã nguồn và hiệu suất của dịch vụ liên quan sẽ cực kỳ cao để tránh lỗi nghiệp vụ. Hơn nữa, nếu lưu lượng truy cập tăng đột biến, các tác vụ quan trọng và không quan trọng sẽ bị chặn lại cùng nhau. Vì vậy, chúng ta cần sử dụng một hàng đợi tin nhắn. Khi nhận được phản hồi thanh toán, chúng ta chỉ xử lý vài thao tác cốt lõi rồi đẩy tin nhắn vào hàng đợi. Sau đó, các bên liên quan sẽ tiêu thụ tin nhắn này để thực hiện các nhiệm vụ phụ như gửi thông báo chăm sóc khách hàng, cập nhật điểm thưởng, v.v.

Ví dụ này không phải là một ví dụ điển hình nhất về việc "giảm tải và cân bằng khối lượng công việc", nhưng nó vẫn là một trường hợp sử dụng phổ biến của hàng đợi tin nhắn. Để hiểu rõ hơn về việc giảm tải, hãy tưởng tượng rằng có 10.000 yêu cầu tới hệ thống trong một khoảng thời gian ngắn, trong khi hệ thống chỉ hỗ trợ tối đa 1.000 QPS. Trong trường hợp bình thường, hệ thống sẽ ngừng hoạt động hoặc bị giới hạn lưu lượng. Để đảm bảo hệ thống hoạt động bình thường, chúng ta có thể đẩy tất cả các yêu cầu này vào hàng đợi tin nhắn và tiêu thụ chúng theo khả năng xử lý của máy chủ.

Bây giờ, hãy cùng tìm hiểu RocketMQ trông như thế nào nhé!

RocketMQ bao gồm bốn thành phần chính: NameServer, Broker, Producer, Consumer.

NameServer đóng vai trò như một trung tâm đăng ký đơn giản cho các Topic. Nó tương tự như Zookeeper trong Dubbo, hỗ trợ đăng ký và phát hiện động các Broker. NameServer có hai chức năng chính:

  • Quản lý Broker: NameServer nhận thông tin đăng ký từ các cụm Broker và lưu trữ chúng dưới dạng dữ liệu cơ bản cho thông tin định tuyến. Đồng thời, nó kiểm tra trạng thái sống còn của các Broker thông qua cơ chế kiểm tra nhịp tim.
  • Quản lý thông tin định tuyến: Mỗi NameServer sẽ lưu giữ thông tin định tuyến của toàn bộ cụm Broker và thông tin hàng đợi cho phép truy vấn bởi client.Producer và Consumer có thể thông qua NameServer để biết thông tin định tuyến của cụm Broker, từ đó gửi và tiêu thụ tin nhắn.

NameServer thường được triển khai dưới dạng cụm, các instance không giao tiếp thông tin lẫn nhau. Mỗi Broker đăng ký thông tin định tuyến của mình lên mọi NameServer, vì vậy mỗi instance NameServer đều có một bản sao đầy đủ của thông tin định tuyến. Nếu một NameServer dừng hoạt động do bất kỳ lý do nào, các Broker vẫn có thể đồng bộ thông tin định tuyến lên các NameServer bóng đá trực tiếp khác, và Producer, Consumer vẫn có thể cảm nhận được thông tin định tuyến của Broker một cách động.

Áp lực lên NameServer không quá lớn, chủ yếu chịu trách nhiệm duy trì nhịp tim và cung cấp dữ liệu mối quan hệ giữa Topic và Broker. Tuy nhiên, cần lưu ý rằng khi Broker gửi nhịp tim đến NameServer, nó sẽ mang theo thông tin của tất cả các Topic mà nó quản lý. Nếu số lượng Topic quá lớn, kích thước dữ liệu trong mỗi nhịp tim có thể trở nên rất lớn, dẫn đến thất bại truyền mạng và kết quả là NameServer có thể nhầm lẫn rằng Broker đã thất bại trong việc gửi nhịp tim.

Broker chịu trách nhiệm chính về lưu trữ, chuyển giao và truy vấn tin nhắn cũng như đảm bảo tính sẵn sàng cao của dịch vụ. Để thực hiện các chức năng này, Broker bao gồm các mô-đun con quan trọng sau:

  • Remoting Module: Là thực thể của toàn bộ Broker, chịu trách nhiệm xử lý các yêu cầu từ client.
  • Client Manager: Quản lý các client (Producer/Consumer) và duy trì thông tin đăng ký Topic của Consumer.
  • Store Service: Cung cấp API đơn giản và dễ sử dụng để xử lý lưu trữ tin nhắn vào ổ cứng vật lý và chức năng truy vấn.
  • HA Service: Dịch vụ sẵn sàng cao, cung cấp chức năng đồng bộ dữ liệu giữa Master Broker và Slave Broker.
  • Index Service: Dựa trên Message Key để lập chỉ mục cho các tin nhắn được gửi đến Broker, giúp truy vấn nhanh chóng.
  1. Cân bằng tải: Thông tin Topic được lưu trữ trên Broker, Topic được chia thành nhiều hàng đợi và phân tán đều trên các Broker khác nhau. Cơ chế gửi của Producer đảm bảo rằng các tin nhắn được phân bổ đều đến tất cả các hàng đợi, giúp đạt được hiệu quả cân bằng tải cho toàn bộ tin nhắn trên mỗi Broker.

  2. Khả năng mở rộng động (cho tin nhắn không theo thứ tự): Khả năng mở rộng của Broker thể hiện ở hai chiều kích: Topic và Broker.

    • Chiều kích Topic: Nếu một Topic có lưu lượng tin nhắn rất lớn nhưng áp lực tổng thể của cụm vẫn thấp, bạn có thể tăng số lượng hàng đợi của Topic đó. Số lượng hàng đợi của Topic tỷ lệ thuận với tốc độ gửi và tiêu thụ.
    • Chiều kích Broker: Nếu áp lực của cụm tăng cao, bạn có thể mở rộng bằng cách thêm máy chủ mới và triển khai Broker. Sau khi Broker mới khởi chạy, nó sẽ đăng ký với NameServer, và Producer, Consumer sẽ phát hiện ra Broker mới thông qua NameServer và kết nối trực tiếp để gửi và nhận tin nhắn.
  3. Tính sẵn sàng cao & đáng tin cậy cao:

    • Sẵn sàng cao: Khi triển khai cụm, các Broker thường được cấu hình theo mô hình chủ-từ (master-slave). Máy từ đồng bộ dữ liệu từ máy chủ và có thể cung cấp dịch vụ tiêu thụ khi máy chủ gặp sự cố, nhưng không cung cấp dịch vụ ghi.
    • Đáng tin cậy cao: Tất cả các tin nhắn gửi đến Broker có thể được ghi đồng bộ hoặc không đồng bộ vào đĩa. Trong chế độ ghi đồng bộ, tin nhắn chỉ được coi là thành công khi nó được ghi vào tập tin vật lý. Trong chế độ ghi không đồng bộ, chỉ có sự cố mất điện đột ngột mới có thể gây ra mất mát tin nhắn.

Producer thiết lập kết nối dài hạn với một node bất kỳ trong cụm NameServer (được chọn ngẫu nhiên), định kỳ lấy thông tin định tuyến Topic từ NameServer và thiết lập kết nối dài hạn với Master cung cấp dịch vụ Topic. Producer hoàn toàn vô trạng thái và có thể triển khai dưới dạng cụm. RocketMQ cung cấp ba phương thức gửi tin:

  • Đồng bộ: Được sử dụng rộng rãi trong các tình huống yêu cầu độ tin cậy cao, chẳng hạn như thông báo quan trọng, hệ thống thông báo SMS, tiếp thị SMS.
  • Không đồng bộ: Thường được sử dụng trong các tình huống nhạy cảm với thời gian phản hồi, nơi tin nhắn được gửi ngay lập tức và xử lý hậu cần thông qua callback.
  • Một lần: Được sử dụng trong các tình huống yêu cầu độ tin cậy trung bình, chẳng hạn như thu thập nhật ký, nơi tin nhắn được gửi đi mà không cần chờ kết quả phản hồi hoặc xử lý callback.

Khi gửi tin nhắn, Producer sẽ tự động luân phiên qua tất cả các Broker có sẵn để gửi tin nhắn. Mỗi tin nhắn được gửi thành công, Producer sẽ chuyển sang Broker khác để gửi tin nhắn tiếp theo, đảm bảo rằng các tin nhắn được phân bổ đều trên tất cả các Broker.

Consumer thiết lập kết nối dài hạn với một node bất kỳ trong cụm NameServer (được chọn ngẫu nhiên), định kỳ lấy thông tin định tuyến Topic từ NameServer và thiết lập kết nối dài hạn với cả Master và Slave cung cấp dịch vụ Topic. Consumer có thể đăng ký tin nhắn từ Master hoặc Slave. Khi Consumer kéo tin nhắn từ Master, máy chủ Master sẽ gợi ý cho lần kéo tiếp theo dựa trên khoảng cách giữa vị trí kéo hiện tại và vị trí lớn nhất, cũng như khả năng đọc từ Slave.

Trước tiên, hãy thảo luận về các chế độ tiêu thụ của Consumer:

  • Tiêu thụ theo cụm: Một Topic có thể được phân chia để tiêu thụ bởi tất cả các Consumer có cùng ID. Ví dụ: Nếu TopicA có 6 hàng đợi và có 2 Consumer với cùng ID, mỗi Consumer sẽ tiêu thụ 3 hàng đợi. Nếu thêm một Consumer khác với cùng ID, mỗi Consumer sẽ tiêu thụ 2 hàng đợi.
  • Tiêu thụ theo phát sóng: Mỗi Consumer tiêu thụ tất cả các hàng đợi của Topic.

Cân bằng tải ở phía Consumer, trong chế độ tiêu thụ theo cụm, đảm bảo rằng tất cả các instance Consumer có cùng ID sẽ tiêu thụ đều các hàng đợi của Topic.

Loại Consumer từ góc độ người dùng:

  • PullConsumer: Chủ động kéo tin nhắn từ Brokers. Người dùng thông thường sẽ gọi phương thức kéo tin nhắn từ máy chủ Broker và có quyền kiểm soát quá trình này. Ngay sau khi nhận được loạt tin nhắn, ứng dụng sẽ bắt đầu quá trình tiêu thụ.
  • PushConsumer: Loại Consumer mà Broker sẽ chủ động đẩy tin nhắn đến phía tiêu thụ khi nhận được dữ liệu. Chế độ này thường có tính thời gian thực cao hơn.

####补充一些概念 Topic: Là tập hợp các tin nhắn thuộc cùng một loại, mỗi Topic chứa nhiều tin nhắn và mỗi tin nhắn chỉ thuộc một Topic duy nhất. Đây là đơn vị cơ bản để đăng ký tin nhắn trong RocketMQ. Topic có mối quan hệ rất lỏng lẻo với Producer và Consumer. Một Topic có thể có 0 hoặc nhiều Producer gửi tin nhắn, và một Producer có thể gửi tin nhắn đến nhiều Topic khác nhau. Từ góc độ Consumer, một Topic có thể được đăng ký bởi 0 hoặc nhiều nhóm Consumer, và một nhóm Consumer có thể đăng ký một hoặc nhiều Topic miễn là các instance trong nhóm giữ nguyên đăng ký của họ.

Message: Là đơn vị nhỏ nhất của dữ liệu được sản xuất và tiêu thụ trong hệ thống tin nhắn. Mỗi tin nhắn phải thuộc về một Topic. Trong RocketMQ, mỗi tin nhắn có một Message ID duy nhất và có thể mang theo một Key có ý nghĩa nghiệp vụ. Hệ thống cung cấp chức năng truy vấn tin nhắn qua Message ID và Key.

Message Queue: Một Topic có thể được chia thành một hoặc nhiều sub-topics ("hàng đợi tin nhắn").

Tag: Là nhãn được gắn cho tin nhắn, giúp phân biệt các loại tin nhắn khác nhau trong cùng một Topic. Tin nhắn từ cùng một đơn vị nghiệp vụ có thể được gắn nhãn khác nhau tùy theo mục đích nghiệp vụ. Tag giúp giữ cho mã nguồn sạch sẽ và mạch lạc, đồng thời tối ưu hóa hệ thống truy vấn của RocketMQ. Consumer có thể sử dụng Tag để thực hiện các logic tiêu thụ khác nhau cho các sub-topics khác nhau, tăng cường khả năng mở rộng.

Message Order: Khi sử dụng DefaultMQPushConsumer, bạn cần xác định cách tiêu thụ tin nhắn:

  • Orderly: Tiêu thụ tin nhắn theo thứ tự, nghĩa là thứ tự tiêu thụ trùng khớp với thứ tự gửi từ Producer.
  • Concurrently: Tiêu thụ song song. Số lượng tối đa các tin nhắn được tiêu thụ cùng lúc chỉ bị giới hạn bởi số lượng luồng trong pool thread của mỗi client Consumer.

Consumer Group: Là tập hợp các Consumer cùng loại, thường tiêu thụ cùng loại tin nhắn và có cùng logic tiêu thụ. Nhóm Consumer giúp dễ dàng đạt được mục tiêu cân bằng tải và dung sai trong việc tiêu thụ tin nhắn. Lưu ý rằng tất cả các instance Consumer trong cùng một nhóm phải đăng ký cùng các Topic.

Producer Group: Là tập hợp các Producer cùng loại, thường gửi cùng loại tin nhắn và có cùng logic gửi. Nếu tin nhắn là giao dịch và Producer gốc bị sập sau khi gửi, máy chủ Broker sẽ liên lạc với các instance Producer khác trong cùng một nhóm để cam kết hoặc hoàn tác tiêu thụ.

Nội dung trên chủ yếu dựa trên tài liệu GitHub của RocketMQ và một số bài viết chất lượng từ cộng đồng mạng. Nếu có vi phạm bản quyền, vui lòng liên hệ để xóa bỏ.