+3

Tính nhất quán và độ tin cậy trong hệ thống Message Broker

Source: https://www.tuanh.net/blog/oop/consistency-and-reliability-concerns-within-the-message-broker-system

Trong các hệ thống phân tán hiện đại, môi giới tin nhắn đóng vai trò quan trọng trong việc truyền dữ liệu giữa các thành phần ứng dụng. Tuy nhiên, đảm bảo tính nhất quán và độ tin cậy trong các hệ thống này có thể là một thách thức. Trong bài viết này, chúng ta sẽ khám phá một số vấn đề phổ biến liên quan đến tính nhất quán và độ tin cậy trong hệ thống môi giới tin nhắn và thảo luận cách giải quyết chúng.

1. Tính nhất quán trong Message Broker

Một hệ thống message broker cung cấp tính nhất quán dữ liệu, đảm bảo rằng tất cả các thành phần của hệ thống có một cái nhìn đáng tin cậy và cập nhật về dữ liệu.

1.1 Số lượng tin nhắn nhất quán

Đảm bảo việc giao và nhận tin nhắn đồng đều là một mối quan tâm rộng rãi. Lỗi mạng hoặc hệ thống có thể phá vỡ tính nhất quán này, dẫn đến mất hoặc trùng lặp tin nhắn. Để giải quyết vấn đề này, nhiều hệ thống message broker triển khai các tính năng như:

  • Xác nhận (ACKs): Hệ thống yêu cầu người nhận gửi lại một xác nhận sau khi nhận được tin nhắn. Điều này giúp đảm bảo rằng tin nhắn đã được nhận thành công.
  • Tái thử: Hệ thống cung cấp các cơ chế để tự động gửi lại các tin nhắn không được gửi hoặc bị mất.

1.2 Nhất quán dữ liệu

Tính nhất quán dữ liệu giữa nhiều broker trong các hệ thống phân tán có thể khó đạt được, đặc biệt là trong các môi trường đồng thời cao. Một số kỹ thuật đã được sử dụng để giải quyết vấn đề này, bao gồm:

  • Sao chép: Tạo nhiều bản sao dữ liệu trên các broker khác nhau để đảm bảo rằng nếu một broker bị lỗi, dữ liệu vẫn có thể được truy cập từ các broker khác.
  • Giao thức đồng thuận: Sử dụng các giao thức đồng thuận như Paxos hoặc Raft để đảm bảo rằng tất cả các broker đồng ý về trạng thái của hệ thống.

2. Độ tin cậy trong Message Brokers

Độ tin cậy của một hệ thống message broker liên quan đến khả năng tiếp tục hoạt động bình thường ngay cả khi gặp lỗi. Các yếu tố ảnh hưởng đến độ tin cậy bao gồm:

2.1. Khả năng tự phục hồi

Một hệ thống đáng tin cậy nên có khả năng tự phục hồi sau khi gặp lỗi. Một số cách để cải thiện khả năng tự phục hồi bao gồm:

  • Cơ chế chuyển đổi lỗi (Failover): Tự động chuyển sang một broker dự phòng nếu broker chính gặp lỗi.
  • Kiểm tra sức khỏe: Giám sát trạng thái của broker để phát hiện và giải quyết các vấn đề trước khi chúng ảnh hưởng đến hệ thống

2.2. Đảm bảo khả năng mở rộng

Để đáp ứng nhu cầu ngày càng tăng mà không ảnh hưởng đến độ tin cậy, hệ thống phải được thiết kế với khả năng mở rộng. Điều này có thể bao gồm:

  • Mở rộng ngang: Thêm nhiều broker vào hệ thống để phân phối tải và cải thiện hiệu suất.
  • Cân bằng tải: Phân phối tin nhắn đều giữa các broker để tránh quá tải.

3. Tin nhắn lặp lại trong Message Broker

3.1 Bối cảnh

Tôi có một hệ thống Google Pub/Sub, được cấu hình như sau.

gcloud pubsub topics create $TOPIC_ID --project=$PROJECT_ID

gcloud alpha pubsub subscriptions create $SUBSCRIPTION_ID --topic=$TOPIC_ID --project=$PROJECT_ID 
        --dead-letter-topic=$DEAD_LETTER_TOPIC_ID 
        --dead-letter-topic-project=$PROJECT_ID 
        --max-delivery-attempts=5 
        --ack-deadline=90 
        --message-retention-duration="7d" 
        --min-retry-delay="10s" 
        --max-retry-delay="20s" 
        --expiration-period="never"

Và một subscriber có cấu hình như sau:

public  Subscriber.Builder configSubscriberBuilder(Subscriber.Builder builder){
	FlowControlSettings flowControlSettings =
            FlowControlSettings.newBuilder()
                    .setMaxOutstandingElementCount(500L)
                    .setMaxOutstandingRequestBytes(50L * 1024L * 1024L)
                    .build();

    int cores = Runtime.getRuntime().availableProcessors();
    int pullCount = 1;
    int cpuUsed = cores/pullCount;
    ExecutorProvider executorProvider =
            InstantiatingExecutorProvider.newBuilder().setExecutorThreadCount(cpuUsed).build();  
    builder.setFlowControlSettings(flowControlSettings);
    builder.setParallelPullCount(pullCount);
    builder.setMaxAckExtensionPeriod(Duration.ofSeconds(30));
    builder.setExecutorProvider(executorProvider);
    
    return builder;
}

Tham số trên có nghĩa là:

  • Sử dụng số lượng luồng bằng với số lượng luồng vật lý để xử lý tin nhắn.
  • Số lượng tin nhắn được kéo sẽ đáp ứng một trong các điều kiện sau: Điều kiện A: Tối đa 500 tin nhắn sẽ được kéo. Điều kiện B: Tổng kích thước của tất cả các tin nhắn được kéo phải nhỏ hơn 50MB. ack-deadline=90 có nghĩa là thời gian tối đa cho phép cho một tin nhắn ACK là 90 giây. Để giải thích thêm về hệ thống Pub/Sub của Google: Khi một tin nhắn được gửi đến một Topic, nó sẽ được lấy và lưu trữ bởi các Subscription. Khi một ứng dụng kết nối với một Subscription, nó sẽ kéo các tin nhắn dựa trên cấu hình của Subscription và Subscriber và giữ các tin nhắn đó trong một Message Container để xử lý dần dần. Sau khi chúng được xử lý hoàn toàn, nó sẽ tiếp tục kéo thêm tin nhắn và làm tương tự.

image.png

Quá trình xử lý bên trong dịch vụ B sẽ diễn ra như sau:

image.png

Ví dụ, các tin nhắn trải qua quá trình xử lý thông qua các cuộc gọi đến dịch vụ D, E và F. Khi quá trình xử lý này hoàn tất, dịch vụ B gửi một xác nhận (ACK) đến đăng ký để chỉ ra rằng tin nhắn đã được xử lý thành công.

image.png

Điều này có nghĩa là các tin nhắn phải được hoàn thành trước khi hết thời gian chờ xác nhận (ACK).

3.2 Lý do

Như đã đề cập ở trên, nếu tất cả các tin nhắn không thể được xử lý trong vòng 90 giây, thì ...

image.png

150 tin nhắn còn lại sẽ được thử lại trên dịch vụ B. Vì chúng đã vượt quá thời gian chờ, chúng không thể được xác nhận và sẽ được trả lại cho đăng ký để xử lý lại ít nhất một lần.

3.3 Một số cách xử lý

Tôi đề xuất các giải pháp sau:

  • Để tối ưu hóa việc sử dụng tài nguyên, chúng ta có thể thực hiện kiểm thử tải trên các hàm chịu trách nhiệm xử lý tin nhắn. Bằng cách xác định thông lượng tối đa của các hàm này, chúng ta có thể cấu hình một người đăng ký để kéo một số lượng tin nhắn phù hợp. Điều này sẽ ngăn chặn việc quá tải hệ thống với nhiều tin nhắn hơn khả năng xử lý của nó.
  • Để đảm bảo tính idempotent của hệ thống, điều quan trọng là triển khai một cơ chế để kiểm tra sự tồn tại của các bản ghi trong các hàm được gọi bởi dịch vụ D, E và F. Kiểm tra này sẽ đảm bảo rằng một hành động không được thực thi nhiều lần cho cùng một yêu cầu, ngay cả khi yêu cầu được lặp lại.

4. Kết luận

Tính nhất quán và độ tin cậy là vô cùng quan trọng trong việc đảm bảo hiệu suất và sự vững chắc của một hệ thống môi giới tin nhắn. Bằng cách hiểu và giải quyết các mối quan tâm về tính nhất quán và độ tin cậy, bạn có thể xây dựng các hệ thống phân tán mạnh mẽ và đáng tin cậy phù hợp với yêu cầu của các ứng dụng hiện đại. Hãy triển khai các thực tiễn và kỹ thuật tốt nhất để đảm bảo hệ thống của bạn hoạt động hiệu quả và ổn định liên tục. Nếu bạn có bất kỳ câu hỏi nào, vui lòng để lại bình luận bên dưới hộp chat để thảo luận thêm. Cảm ơn bạn đã dành thời gian và chúng tôi mong muốn được kết nối với bạn một lần nữa.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí