RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm

RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm

Khả năng chịu lỗi và tính sẵn sàng cao là những chủ đề lớn, vì vậy chúng tôi sẽ dành các bài viết riêng cho RabbitMQ và Kafka. Bài viết này nói về RabbitMQ, và bài tiếp theo là về Kafka, so sánh với RabbitMQ. Đây là một bài viết dài, vì vậy hãy thoải mái.

Chúng ta hãy xem xét các chiến lược có khả năng chịu lỗi, tính nhất quán và tính sẵn sàng cao (HA) cũng như sự đánh đổi mà mỗi chiến lược thực hiện. RabbitMQ có thể chạy trên một cụm nút - và sau đó được phân loại là hệ thống phân tán. Khi nói đến hệ thống phân tán, chúng ta thường nói đến tính nhất quán và tính sẵn sàng.

Những khái niệm này mô tả cách một hệ thống hoạt động khi nó bị lỗi. Lỗi kết nối mạng, lỗi máy chủ, lỗi ổ cứng, máy chủ tạm thời không khả dụng do thu gom rác, mất gói hoặc kết nối mạng bị chậm. Tất cả điều này có thể dẫn đến mất dữ liệu hoặc xung đột. Hóa ra là hầu như không thể thiết lập một hệ thống vừa hoàn toàn nhất quán (không mất dữ liệu, không phân kỳ dữ liệu) vừa có sẵn (sẽ chấp nhận đọc và ghi) cho tất cả các tình huống lỗi.

Chúng ta sẽ thấy rằng tính nhất quán và tính khả dụng nằm ở hai đầu đối diện nhau và bạn cần chọn cách tối ưu hóa. Tin vui là với RabbitMQ, sự lựa chọn này là có thể. Bạn có những loại đòn bẩy “ngớ ngẩn” này để chuyển sự cân bằng theo hướng nhất quán hơn hoặc khả năng tiếp cận cao hơn.

Chúng tôi sẽ đặc biệt chú ý đến cấu hình nào dẫn đến mất dữ liệu do các bản ghi đã được xác nhận. Có một chuỗi trách nhiệm giữa nhà xuất bản, nhà môi giới và người tiêu dùng. Sau khi tin nhắn được chuyển đến người môi giới, nhiệm vụ của anh ta là không được làm mất tin nhắn. Khi người môi giới xác nhận việc nhà xuất bản đã nhận được tin nhắn, chúng tôi không mong đợi nó sẽ bị mất. Nhưng chúng ta sẽ thấy rằng điều này thực sự có thể xảy ra tùy thuộc vào cấu hình nhà môi giới và nhà xuất bản của bạn.

Khả năng phục hồi nút đơn nguyên thủy

Xếp hàng/định tuyến linh hoạt

Có hai loại hàng đợi trong RabbitMQ: bền và không bền. Tất cả hàng đợi được lưu trong cơ sở dữ liệu Mnesia. Hàng đợi lâu bền được quảng cáo lại khi khởi động nút và do đó vẫn tồn tại khi khởi động lại, sự cố hệ thống hoặc sự cố máy chủ (miễn là dữ liệu vẫn được duy trì). Điều này có nghĩa là miễn là bạn tuyên bố định tuyến (trao đổi) và hàng đợi có khả năng linh hoạt, cơ sở hạ tầng xếp hàng/định tuyến sẽ trực tuyến trở lại.

Hàng đợi và định tuyến dễ bay hơi sẽ bị xóa khi nút được khởi động lại.

Tin nhắn liên tục

Chỉ vì hàng đợi bền không có nghĩa là tất cả các tin nhắn của nó sẽ tồn tại khi nút khởi động lại. Chỉ những tin nhắn do nhà xuất bản đặt là đàn hồi (kiên trì). Các tin nhắn liên tục sẽ tạo thêm tải cho nhà môi giới, nhưng nếu việc mất tin nhắn là không thể chấp nhận được thì không có lựa chọn nào khác.

RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm
Cơm. 1. Ma trận bền vững

Phân cụm với phản ánh hàng đợi

Để tồn tại khi mất đi một nhà môi giới, chúng ta cần có sự dự phòng. Chúng ta có thể kết hợp nhiều nút RabbitMQ thành một cụm, sau đó thêm dự phòng bổ sung bằng cách sao chép hàng đợi giữa nhiều nút. Bằng cách này, nếu một nút bị lỗi, chúng tôi sẽ không mất dữ liệu và vẫn khả dụng.

Phản ánh hàng đợi:

  • một hàng đợi chính (chính), nhận tất cả các lệnh ghi và đọc
  • một hoặc nhiều máy nhân bản nhận tất cả tin nhắn và siêu dữ liệu từ hàng đợi chính. Những tấm gương này không có ở đó để chia tỷ lệ mà hoàn toàn là để dự phòng.

RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm
Cơm. 2. Phản chiếu hàng đợi

Phản ánh được thiết lập bởi chính sách thích hợp. Trong đó, bạn có thể chọn hệ số sao chép và thậm chí cả các nút mà hàng đợi sẽ được đặt trên đó. Ví dụ:

  • ha-mode: all
  • ha-mode: exactly, ha-params: 2 (một chủ và một gương)
  • ha-mode: nodes, ha-params: rabbit@node1, rabbit@node2

Xác nhận của nhà xuất bản

Để đạt được bản ghi nhất quán, cần phải có Xác nhận của nhà xuất bản. Không có chúng, có nguy cơ tin nhắn bị mất. Xác nhận sẽ được gửi đến nhà xuất bản sau khi tin nhắn được ghi vào đĩa. RabbitMQ ghi tin nhắn vào đĩa không phải khi nhận được mà theo định kỳ, trong khoảng vài trăm mili giây. Khi một hàng đợi được sao chép, một xác nhận chỉ được gửi sau khi tất cả các máy nhân bản cũng đã ghi bản sao thông báo của chúng vào đĩa. Điều này có nghĩa là việc sử dụng xác nhận sẽ làm tăng thêm độ trễ, nhưng nếu bảo mật dữ liệu là quan trọng thì chúng là cần thiết.

Hàng đợi chuyển đổi dự phòng

Khi một nhà môi giới thoát hoặc gặp sự cố, tất cả các nhà lãnh đạo hàng đợi (chính) trên nút đó sẽ gặp sự cố cùng với nó. Sau đó, cụm sẽ chọn gương cũ nhất của mỗi chủ và thăng cấp nó thành chủ mới.

RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm
Cơm. 3. Nhiều hàng đợi được phản ánh và chính sách của chúng

Nhà môi giới 3 đi xuống. Lưu ý rằng máy nhân bản Hàng C trên Nhà môi giới 2 đang được thăng cấp thành chính. Cũng lưu ý rằng một bản sao mới đã được tạo cho Hàng đợi C trên Nhà môi giới 1. RabbitMQ luôn cố gắng duy trì hệ số sao chép được chỉ định trong chính sách của bạn.

RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm
Cơm. 4. Broker 3 bị lỗi khiến hàng đợi C bị lỗi

Nhà môi giới tiếp theo 1 thất thủ! Chúng tôi chỉ còn lại một nhà môi giới. Gương Hàng B được thăng cấp thành chủ.

RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm
Hình 5

Chúng tôi đã trả lại Nhà môi giới 1. Bất kể dữ liệu vẫn tồn tại như thế nào sau khi mất và phục hồi nhà môi giới, tất cả các thông báo hàng đợi được phản chiếu sẽ bị loại bỏ khi khởi động lại. Điều này rất quan trọng cần lưu ý vì sẽ có hậu quả. Chúng ta sẽ sớm xem xét những hàm ý này. Vì vậy, Nhà môi giới 1 hiện lại là thành viên của cụm và cụm cố gắng tuân thủ các chính sách và do đó tạo ra các bản sao trên Nhà môi giới 1.

Trong trường hợp này, việc mất Nhà môi giới 1 và dữ liệu cũng như dữ liệu đều bị mất hoàn toàn, do đó Hàng đợi B không được phản ánh đã bị mất hoàn toàn.

RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm
Cơm. 6. Môi giới 1 trở lại hoạt động

Nhà môi giới 3 đã trực tuyến trở lại, vì vậy hàng đợi A và B lấy lại các bản sao được tạo trên đó để đáp ứng chính sách HA của họ. Nhưng bây giờ tất cả các hàng đợi chính đều nằm trên một nút! Điều này không lý tưởng, sự phân bổ đồng đều giữa các nút sẽ tốt hơn. Thật không may, ở đây không có nhiều lựa chọn để cân bằng lại các bậc thầy. Chúng ta sẽ quay lại vấn đề này sau vì trước tiên chúng ta cần xem xét việc đồng bộ hóa hàng đợi.

RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm
Cơm. 7. Nhà môi giới 3 trở lại hoạt động. Tất cả các hàng đợi chính trên một nút!

Vì vậy, bây giờ bạn nên có ý tưởng về cách các gương cung cấp khả năng dự phòng và khả năng chịu lỗi. Điều này đảm bảo tính khả dụng trong trường hợp có một nút bị lỗi và bảo vệ khỏi mất dữ liệu. Nhưng chúng ta vẫn chưa xong vì trên thực tế nó phức tạp hơn nhiều.

Đồng bộ hóa

Khi tạo một máy nhân bản mới, tất cả các tin nhắn mới sẽ luôn được sao chép vào máy nhân bản này và bất kỳ máy nhân bản nào khác. Đối với dữ liệu hiện có trong hàng đợi chính, chúng ta có thể sao chép nó sang một bản sao mới, bản sao này sẽ trở thành bản sao hoàn chỉnh của bản gốc. Chúng tôi cũng có thể chọn không sao chép các tin nhắn hiện có và để hàng đợi chính và máy nhân bản mới hội tụ kịp thời, với các tin nhắn mới đến ở cuối và các tin nhắn hiện có rời khỏi đầu hàng đợi chính.

Việc đồng bộ hóa này được thực hiện tự động hoặc thủ công và được quản lý bằng chính sách hàng đợi. Hãy xem một ví dụ.

Chúng tôi có hai hàng đợi được nhân đôi. Hàng đợi A được đồng bộ hóa tự động và Hàng đợi B được đồng bộ hóa thủ công. Cả hai hàng đợi đều chứa mười tin nhắn.

RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm
Cơm. 8. Hai hàng đợi với các chế độ đồng bộ hóa khác nhau

Bây giờ chúng tôi đang mất Nhà môi giới 3.

RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm
Cơm. 9. Môi giới 3 thất thủ

Nhà môi giới 3 trở lại hoạt động. Cụm tạo một bản sao cho mỗi hàng đợi trên nút mới và tự động đồng bộ hóa Hàng đợi A mới với nút chính. Tuy nhiên, bản sao của Hàng đợi B mới vẫn trống. Bằng cách này, chúng tôi có toàn bộ dự phòng trên Hàng đợi A và chỉ có một bản sao cho các tin nhắn Hàng đợi B hiện có.

RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm
Cơm. 10. Máy nhân bản mới của Hàng đợi A nhận được tất cả các tin nhắn hiện có, nhưng máy nhân bản mới của Hàng đợi B thì không.

Mười tin nhắn nữa đến trong cả hai hàng đợi. Sau đó, Nhà môi giới 2 gặp sự cố và Hàng đợi A quay trở lại máy nhân bản cũ nhất trên Nhà môi giới 1. Không bị mất dữ liệu khi nó bị lỗi. Trong Hàng đợi B, có XNUMX tin nhắn trong bản gốc và chỉ có XNUMX tin nhắn trong bản sao vì hàng đợi này không bao giờ sao chép XNUMX tin nhắn ban đầu.

RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm
Cơm. 11. Hàng đợi A quay trở lại Nhà môi giới 1 mà không mất tin nhắn

Mười tin nhắn nữa đến trong cả hai hàng đợi. Bây giờ Nhà môi giới 1 gặp sự cố. Hàng đợi A dễ dàng chuyển sang máy nhân bản mà không làm mất tin nhắn. Tuy nhiên, Hàng B đang gặp sự cố. Tại thời điểm này, chúng tôi có thể tối ưu hóa tính khả dụng hoặc tính nhất quán.

Nếu chúng ta muốn tối ưu hóa khả năng tiếp cận thì chính sách ha-thúc đẩy khi thất bại nên được cài đặt trong luôn luôn. Đây là giá trị mặc định, vì vậy bạn không thể chỉ định chính sách nào cả. Trong trường hợp này, về cơ bản chúng tôi cho phép xảy ra lỗi trong các máy nhân bản không đồng bộ. Điều này sẽ khiến tin nhắn bị mất nhưng hàng đợi vẫn có thể đọc và ghi được.

RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm
Cơm. 12. Hàng đợi A được khôi phục về Nhà môi giới 3 mà không làm mất tin nhắn. Hàng đợi B quay trở lại Nhà môi giới 3 với mười tin nhắn bị mất

Chúng ta cũng có thể cài đặt ha-promote-on-failure thành ý nghĩa when-synced. Trong trường hợp này, thay vì quay trở lại bản sao, hàng đợi sẽ đợi cho đến khi Nhà môi giới 1 với dữ liệu của nó quay trở lại chế độ trực tuyến. Sau khi trả về, hàng đợi chính sẽ quay trở lại Nhà môi giới 1 mà không bị mất dữ liệu. Sự sẵn có được hy sinh để bảo mật dữ liệu. Nhưng đây là một chế độ rủi ro thậm chí có thể dẫn đến mất dữ liệu hoàn toàn, chúng tôi sẽ xem xét ngay sau đây.

RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm
Cơm. 13. Hàng đợi B vẫn không khả dụng sau khi mất Nhà môi giới 1

Bạn có thể hỏi, “Có tốt hơn không nếu không bao giờ sử dụng đồng bộ hóa tự động?” Câu trả lời là đồng bộ hóa là một hoạt động chặn. Trong quá trình đồng bộ hóa, hàng đợi chính không thể thực hiện bất kỳ thao tác đọc hoặc ghi nào!

Hãy xem một ví dụ. Bây giờ chúng tôi có hàng đợi rất dài. Làm thế nào chúng có thể phát triển đến kích thước như vậy? Vì nhiều lý do:

  • Hàng đợi không được sử dụng tích cực
  • Đây là những hàng đợi tốc độ cao và hiện tại người tiêu dùng đang chậm
  • Đó là hàng đợi tốc độ cao, đã có trục trặc và người tiêu dùng đang bắt kịp

RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm
Cơm. 14. Hai hàng đợi lớn với các chế độ đồng bộ hóa khác nhau

Bây giờ Nhà môi giới 3 thất thủ.

RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm
Cơm. 15. Người môi giới 3 ngã, để lại một chủ nhân và một tấm gương trong mỗi hàng đợi

Nhà môi giới 3 trực tuyến trở lại và các bản sao mới được tạo. Hàng đợi chính A bắt đầu sao chép các tin nhắn hiện có sang máy nhân bản mới và trong thời gian này Hàng đợi không khả dụng. Phải mất hai giờ để sao chép dữ liệu, dẫn đến hàng đợi này bị ngừng hoạt động hai giờ!

Tuy nhiên, Hàng đợi B vẫn có sẵn trong toàn bộ thời gian. Cô ấy đã hy sinh một số thứ dư thừa để có được khả năng tiếp cận.

RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm
Cơm. 16. Hàng đợi vẫn không khả dụng trong quá trình đồng bộ hóa

Sau hai giờ, Hàng đợi A cũng sẵn sàng và có thể bắt đầu chấp nhận đọc và ghi lại.

Cập nhật

Hành vi chặn này trong quá trình đồng bộ hóa gây khó khăn cho việc cập nhật các cụm có hàng đợi rất lớn. Tại một thời điểm nào đó, nút chính cần được khởi động lại, điều đó có nghĩa là chuyển sang máy nhân bản hoặc vô hiệu hóa hàng đợi trong khi máy chủ đang được nâng cấp. Nếu chúng tôi chọn chuyển đổi, chúng tôi sẽ mất thông báo nếu các máy nhân bản không được đồng bộ hóa. Theo mặc định, trong thời gian ngừng hoạt động của nhà môi giới, việc chuyển đổi dự phòng sang máy nhân bản không đồng bộ sẽ không được thực hiện. Điều này có nghĩa là ngay khi người môi giới quay lại, chúng tôi không bị mất bất kỳ tin nhắn nào, thiệt hại duy nhất là một hàng đợi đơn giản. Quy tắc ứng xử khi nhà môi giới bị ngắt kết nối được đặt theo chính sách ha-promote-on-shutdown. Bạn có thể đặt một trong hai giá trị:

  • always= quá trình chuyển đổi sang các máy nhân bản không đồng bộ được bật
  • when-synced= chỉ chuyển sang máy nhân bản được đồng bộ hóa, nếu không hàng đợi sẽ không thể đọc được và không thể ghi được. Hàng đợi trở lại phục vụ ngay khi người môi giới quay lại

Bằng cách này hay cách khác, với hàng đợi lớn, bạn phải lựa chọn giữa mất dữ liệu và không có sẵn.

Khi tính khả dụng cải thiện bảo mật dữ liệu

Có một điều phức tạp nữa cần xem xét trước khi đưa ra quyết định. Mặc dù đồng bộ hóa tự động tốt hơn cho việc dự phòng nhưng nó ảnh hưởng đến bảo mật dữ liệu như thế nào? Tất nhiên, với khả năng dự phòng tốt hơn, RabbitMQ ít có khả năng mất các tin nhắn hiện có, nhưng còn các tin nhắn mới từ nhà xuất bản thì sao?

Ở đây bạn cần xem xét những điều sau:

  • Nhà xuất bản có thể chỉ cần trả lại lỗi và yêu cầu người dùng hoặc dịch vụ ngược dòng thử lại sau không?
  • Nhà xuất bản có thể lưu tin nhắn cục bộ hoặc trong cơ sở dữ liệu để thử lại sau không?

Nếu nhà xuất bản chỉ có thể loại bỏ tin nhắn thì trên thực tế, việc cải thiện khả năng truy cập cũng giúp cải thiện tính bảo mật dữ liệu.

Vì vậy, cần phải tìm kiếm sự cân bằng và giải pháp tùy thuộc vào từng tình huống cụ thể.

Sự cố với ha-promote-on-failure=khi được đồng bộ hóa

Ý tưởng ha-thúc đẩy khi thất bại= khi được đồng bộ hóa là chúng tôi ngăn chặn việc chuyển sang máy nhân bản không đồng bộ và do đó tránh mất dữ liệu. Hàng đợi vẫn không thể đọc hoặc ghi được. Thay vào đó, chúng tôi cố gắng khôi phục trình môi giới bị lỗi với dữ liệu còn nguyên vẹn để nó có thể tiếp tục hoạt động như một trình quản lý chính mà không bị mất dữ liệu.

Nhưng (và đây là một chữ nhưng lớn) nếu người môi giới bị mất dữ liệu của mình, thì chúng ta gặp một vấn đề lớn: hàng đợi bị mất! Tất cả dữ liệu đã biến mất! Ngay cả khi bạn có những chiếc gương gần như bắt kịp hàng đợi chính, những chiếc gương đó cũng sẽ bị loại bỏ.

Để thêm lại một nút có cùng tên, chúng ta yêu cầu cụm quên nút bị mất (bằng lệnh rabbitmqctl quên_cluster_node) và bắt đầu một nhà môi giới mới có cùng tên máy chủ. Trong khi cụm ghi nhớ nút bị mất, nó sẽ nhớ hàng đợi cũ và các bản sao không đồng bộ. Khi một cụm được yêu cầu quên nút mồ côi, hàng đợi đó cũng bị lãng quên. Bây giờ chúng ta cần khai báo lại nó. Chúng tôi đã mất tất cả dữ liệu, mặc dù chúng tôi có các bản sao chứa một phần dữ liệu. Sẽ tốt hơn nếu chuyển sang một máy nhân bản không đồng bộ!

Do đó, việc đồng bộ hóa thủ công (và không đồng bộ hóa được) kết hợp với ha-promote-on-failure=when-synced, theo tôi, khá rủi ro. Các tài liệu cho biết tùy chọn này tồn tại để bảo mật dữ liệu nhưng nó là con dao hai lưỡi.

Tái cân bằng tổng thể

Như đã hứa, chúng ta quay lại vấn đề tích lũy tất cả các bậc thầy trên một hoặc một số nút. Điều này thậm chí có thể xảy ra do cập nhật cụm luân phiên. Trong cụm ba nút, tất cả hàng đợi chính sẽ tích lũy trên một hoặc hai nút.

Việc tái cân bằng các bản gốc có thể gặp vấn đề vì hai lý do:

  • Không có công cụ tốt để thực hiện tái cân bằng
  • Đồng bộ hóa hàng đợi

Có bên thứ ba tái cân bằng cắm vào, không được hỗ trợ chính thức. Về plugin của bên thứ ba trong hướng dẫn sử dụng RabbitMQ nói: “Plugin này cung cấp một số công cụ báo cáo và cấu hình bổ sung, nhưng không được nhóm RabbitMQ hỗ trợ hoặc xác minh. Sử dụng có nguy cơ của riêng bạn."

Có một thủ thuật khác để di chuyển hàng đợi chính thông qua chính sách HA. Hướng dẫn đề cập kịch bản vì điều này. Nó hoạt động như thế này:

  • Loại bỏ tất cả các bản sao bằng chính sách tạm thời có mức độ ưu tiên cao hơn chính sách HA hiện tại.
  • Thay đổi chính sách tạm thời HA để sử dụng chế độ nút, chỉ định nút mà hàng đợi chính sẽ được chuyển đến.
  • Đồng bộ hóa hàng đợi để di chuyển đẩy.
  • Sau khi di chuyển hoàn tất, hãy xóa chính sách tạm thời. Chính sách HA ban đầu có hiệu lực và số lượng máy nhân bản cần thiết sẽ được tạo.

Nhược điểm là phương pháp này có thể không hiệu quả nếu bạn có hàng đợi lớn hoặc yêu cầu dự phòng nghiêm ngặt.

Bây giờ hãy xem các cụm RabbitMQ hoạt động như thế nào với các phân vùng mạng.

Mất kết nối

Các nút của hệ thống phân tán được kết nối bằng các liên kết mạng và các liên kết mạng có thể và sẽ bị ngắt kết nối. Tần suất ngừng hoạt động phụ thuộc vào cơ sở hạ tầng cục bộ hoặc độ tin cậy của đám mây đã chọn. Trong mọi trường hợp, hệ thống phân tán phải có khả năng đối phó với chúng. Một lần nữa, chúng ta có sự lựa chọn giữa tính sẵn có và tính nhất quán, và một lần nữa tin tốt là RabbitMQ cung cấp cả hai tùy chọn (không phải cùng một lúc).

Với RabbitMQ chúng ta có hai lựa chọn chính:

  • Cho phép phân chia hợp lý (split-brain). Điều này đảm bảo tính khả dụng nhưng có thể gây mất dữ liệu.
  • Vô hiệu hóa phân tách hợp lý. Có thể dẫn đến mất tính khả dụng trong thời gian ngắn tùy thuộc vào cách khách hàng kết nối với cụm. Cũng có thể dẫn đến tình trạng không có sẵn hoàn toàn trong cụm hai nút.

Nhưng sự tách biệt hợp lý là gì? Đây là khi một cụm chia làm hai do mất kết nối mạng. Ở mỗi bên, các gương được thăng cấp thành một bản chính, do đó cuối cùng sẽ có một số bản chính trên mỗi hàng đợi.

RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm
Cơm. 17. Hàng đợi chính và hai máy nhân bản, mỗi máy ở một nút riêng biệt. Sau đó xảy ra lỗi mạng và một máy nhân bản bị tách ra. Nút được tách ra nhận thấy hai nút còn lại đã rơi ra và quảng bá các gương của nó cho nút chủ. Bây giờ chúng ta có hai hàng đợi chính, cả có thể ghi và có thể đọc được.

Nếu nhà xuất bản gửi dữ liệu đến cả hai bản gốc thì chúng ta sẽ có hai bản sao khác nhau của hàng đợi.

Các chế độ khác nhau của RabbitMQ cung cấp tính khả dụng hoặc tính nhất quán.

Chế độ bỏ qua (mặc định)

Chế độ này đảm bảo khả năng tiếp cận. Sau khi mất kết nối, sự phân tách logic sẽ xảy ra. Sau khi kết nối được khôi phục, quản trị viên phải quyết định ưu tiên phân vùng nào. Bên thua sẽ được khởi động lại và toàn bộ dữ liệu tích lũy của bên đó sẽ bị mất.

RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm
Cơm. 18. Ba nhà xuất bản được liên kết với ba nhà môi giới. Trong nội bộ, cụm định tuyến tất cả các yêu cầu đến hàng đợi chính trên Nhà môi giới 2.

Bây giờ chúng tôi đang mất Nhà môi giới 3. Anh ta thấy rằng các nhà môi giới khác đã sa sút và quảng cáo chiếc gương của mình cho chủ. Đây là cách xảy ra sự phân tách hợp lý.

RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm
Cơm. 19. Phân chia logic (split-brain). Các bản ghi được xếp thành hai hàng chính và hai bản sao sẽ phân kỳ.

Kết nối được khôi phục nhưng vẫn còn sự tách biệt logic. Người quản trị phải chọn bên thua theo cách thủ công. Trong trường hợp bên dưới, quản trị viên khởi động lại Nhà môi giới 3. Tất cả các tin nhắn mà anh ta không thể truyền được sẽ bị mất.

RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm
Cơm. 20. Quản trị viên vô hiệu hóa Nhà môi giới 3.

RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm
Cơm. 21. Quản trị viên khởi động Nhà môi giới 3 và nó tham gia vào cụm, mất tất cả các tin nhắn còn lại ở đó.

Trong thời gian mất kết nối và sau khi được khôi phục, cụm và hàng đợi này vẫn có sẵn để đọc và ghi.

Chế độ tự động chữa lành

Hoạt động tương tự như chế độ Bỏ qua, ngoại trừ việc cụm tự động chọn bên bị mất sau khi tách và khôi phục kết nối. Bên thua sẽ trở về cụm trống và hàng đợi sẽ mất tất cả các tin nhắn chỉ được gửi đến bên đó.

Tạm dừng chế độ thiểu số

Nếu chúng tôi không muốn cho phép phân vùng logic thì lựa chọn duy nhất của chúng tôi là loại bỏ các lần đọc và ghi ở phía nhỏ hơn sau phân vùng cụm. Khi người môi giới thấy rằng nó ở phía nhỏ hơn, nó sẽ tạm dừng công việc, nghĩa là nó sẽ đóng tất cả các kết nối hiện có và từ chối mọi kết nối mới. Mỗi giây một lần, nó sẽ kiểm tra việc khôi phục kết nối. Sau khi kết nối được khôi phục, nó sẽ tiếp tục hoạt động và tham gia vào cụm.

RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm
Cơm. 22. Ba nhà xuất bản được liên kết với ba nhà môi giới. Trong nội bộ, cụm định tuyến tất cả các yêu cầu đến hàng đợi chính trên Nhà môi giới 2.

Sau đó, Nhà môi giới 1 và 2 tách khỏi Nhà môi giới 3. Thay vì thăng cấp bản sao của họ thành chủ, Nhà môi giới 3 tạm dừng và không khả dụng.

RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm
Cơm. 23. Nhà môi giới 3 tạm dừng, ngắt kết nối tất cả máy khách và từ chối yêu cầu kết nối.

Sau khi kết nối được khôi phục, nó sẽ quay trở lại cụm.

Hãy xem một ví dụ khác trong đó hàng đợi chính nằm trên Nhà môi giới 3.

RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm
Cơm. 24. Hàng đợi chính trên Nhà môi giới 3.

Sau đó, tình trạng mất kết nối tương tự cũng xảy ra. Nhà môi giới 3 tạm dừng vì nó ở phía nhỏ hơn. Ở phía bên kia, các nút thấy rằng Nhà môi giới 3 đã rơi ra, do đó, máy nhân bản cũ hơn của Nhà môi giới 1 và 2 được thăng cấp thành chủ.

RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm
Cơm. 25. Chuyển sang Nhà môi giới 2 nếu Nhà môi giới 3 không có sẵn.

Khi kết nối được khôi phục, Nhà môi giới 3 sẽ tham gia cụm.

RabbitMQ vs Kafka: Khả năng chịu lỗi và tính sẵn sàng cao trong các cụm
Cơm. 26. Cụm đã trở lại hoạt động bình thường.

Điều quan trọng cần hiểu ở đây là chúng ta có được sự nhất quán, nhưng chúng ta cũng có thể có được tính sẵn sàng, nếu Chúng tôi sẽ chuyển khách hàng thành công đến hầu hết các phần. Trong hầu hết các tình huống, cá nhân tôi sẽ chọn chế độ Tạm dừng thiểu số, nhưng nó thực sự phụ thuộc vào từng trường hợp cụ thể.

Để đảm bảo tính khả dụng, điều quan trọng là phải đảm bảo rằng máy khách kết nối thành công với máy chủ. Hãy xem xét các lựa chọn của chúng tôi.

Đảm bảo kết nối khách hàng

Chúng tôi có một số tùy chọn về cách hướng máy khách đến phần chính của cụm hoặc tới các nút đang hoạt động (sau khi một nút bị lỗi) sau khi mất kết nối. Trước tiên, hãy nhớ rằng một hàng đợi cụ thể được lưu trữ trên một nút cụ thể, nhưng định tuyến và chính sách được sao chép trên tất cả các nút. Khách hàng có thể kết nối với bất kỳ nút nào và định tuyến nội bộ sẽ hướng dẫn họ đến nơi họ cần đến. Nhưng khi một nút bị treo, nó sẽ từ chối các kết nối, do đó máy khách phải kết nối với một nút khác. Nếu nút rơi ra, anh ấy sẽ không thể làm được gì nhiều.

Lựa chọn của chúng tôi:

  • Cụm được truy cập bằng cách sử dụng bộ cân bằng tải, nó chỉ chuyển qua các nút và máy khách thử kết nối lại cho đến khi thành công. Nếu một nút ngừng hoạt động hoặc bị treo thì các nỗ lực kết nối với nút đó sẽ không thành công nhưng các lần thử tiếp theo sẽ chuyển đến các máy chủ khác (theo kiểu vòng tròn). Điều này phù hợp với trường hợp mất kết nối trong thời gian ngắn hoặc máy chủ bị hỏng sẽ nhanh chóng được khôi phục lại.
  • Truy cập cụm thông qua bộ cân bằng tải và xóa các nút bị treo/không thành công khỏi danh sách ngay khi chúng được phát hiện. Nếu chúng tôi thực hiện việc này một cách nhanh chóng và nếu khách hàng có thể thử lại kết nối thì chúng tôi sẽ đạt được tính khả dụng liên tục.
  • Cung cấp cho mỗi khách hàng một danh sách tất cả các nút và khách hàng chọn ngẫu nhiên một trong số chúng khi kết nối. Nếu nó gặp lỗi khi cố gắng kết nối, nó sẽ di chuyển đến nút tiếp theo trong danh sách cho đến khi kết nối.
  • Xóa lưu lượng truy cập khỏi nút bị lỗi/bị treo bằng DNS. Điều này được thực hiện bằng cách sử dụng một TTL nhỏ.

Những phát hiện

Phân cụm RabbitMQ có những ưu điểm và nhược điểm. Nhược điểm nghiêm trọng nhất đó là:

  • khi tham gia một cụm, các nút sẽ loại bỏ dữ liệu của chúng;
  • chặn đồng bộ hóa khiến hàng đợi không khả dụng.

Mọi quyết định khó khăn đều xuất phát từ hai đặc điểm kiến ​​trúc này. Nếu RabbitMQ có thể lưu dữ liệu khi cụm được nối lại thì việc đồng bộ hóa sẽ nhanh hơn. Nếu nó có khả năng đồng bộ hóa không chặn thì nó sẽ hỗ trợ tốt hơn các hàng đợi lớn. Việc khắc phục hai sự cố này sẽ cải thiện đáng kể hiệu suất của RabbitMQ như một công nghệ nhắn tin có khả năng chịu lỗi và có tính sẵn sàng cao. Tôi sẽ do dự khi giới thiệu RabbitMQ với tính năng phân cụm trong các tình huống sau:

  • Mạng không đáng tin cậy.
  • Lưu trữ không đáng tin cậy
  • Hàng đợi rất dài.

Khi nói đến cài đặt tính sẵn sàng cao, hãy xem xét những điều sau:

  • ha-promote-on-failure=always
  • ha-sync-mode=manual
  • cluster_partition_handling=ignore (hoặc autoheal)
  • tin nhắn liên tục
  • đảm bảo khách hàng kết nối với nút hoạt động khi một số nút bị lỗi

Để nhất quán (bảo mật dữ liệu), hãy xem xét các cài đặt sau:

  • Xác nhận của nhà xuất bản và xác nhận thủ công về phía người tiêu dùng
  • ha-promote-on-failure=when-synced, nếu nhà xuất bản có thể thử lại sau và nếu bạn có bộ nhớ rất đáng tin cậy! Nếu không thì đặt =always.
  • ha-sync-mode=automatic (nhưng đối với các hàng đợi không hoạt động lớn có thể cần phải có chế độ thủ công; đồng thời hãy xem xét liệu việc không có sẵn có khiến tin nhắn bị mất hay không)
  • Tạm dừng chế độ thiểu số
  • tin nhắn liên tục

Chúng tôi chưa đề cập đến tất cả các vấn đề về khả năng chịu lỗi và tính sẵn sàng cao; ví dụ: cách thực hiện các thủ tục hành chính một cách an toàn (chẳng hạn như cập nhật luân phiên). Chúng ta cũng cần nói về liên kết và plugin Shovel.

Nếu tôi bỏ lỡ bất cứ điều gì khác, xin vui lòng cho tôi biết.

Xem thêm của tôi gửi, trong đó tôi thực hiện việc tàn phá cụm RabbitMQ bằng Docker và Blockade để kiểm tra một số tình huống mất thư được mô tả trong bài viết này.

Các bài trước trong loạt bài:
Số 1 - habr.com/ru/company/isumma/blog/416629
Số 2 - habr.com/ru/company/isumma/blog/418389
Số 3 - habr.com/ru/company/isumma/blog/437446

Nguồn: www.habr.com

Thêm một lời nhận xét