2012-02-21 6 views
10

Tôi có một dịch vụ web đang chạy trên một cụm máy chủ. Dịch vụ web này thực hiện một số xử lý nội bộ và sau đó có thể thực hiện cuộc gọi đến dịch vụ bên ngoài chịu phí.Mẫu thiết kế đồng bộ hóa đồng bộ hóa tối ưu hóa

Tôi muốn đặt vào bộ nhớ đệm để nhận được yêu cầu giống hệt với dịch vụ (được đảm bảo), sau đó tôi không phải lặp lại quá trình xử lý, tiết kiệm thời gian/công suất xử lý và cả chi phí phát sinh trong phần bên ngoài của cuộc gọi dịch vụ.

Tuy nhiên, tôi đang đấu tranh để tìm ra cách để quản lý bộ nhớ đệm này khi tôi có những hạn chế sau

  • Dịch vụ này đang chạy trên nhiều máy chủ web cho High Availability và khả năng mở rộng
  • Yêu cầu có thể mất đến 5 giây để trả lời, nhưng trong thời gian đó, tôi có thể đã nhận được 2 hoặc 3 yêu cầu giống hệt khác.

Làm cách nào tôi có thể dừng thực hiện các cuộc gọi dịch vụ khác, cho đến khi cuộc gọi đầu tiên đã phản hồi (do đó có sẵn trong bộ nhớ cache), khi làm việc trong môi trường phân tán.

Tôi đã nghĩ đến việc đặt một mẫu ủy nhiệm trước và xây dựng một hàng đợi các yêu cầu giống hệt nhau trong proxy, để khi trở về đầu tiên, nó cũng có thể trả về cùng một phản hồi cho người khác. Đây có phải là mô hình chính xác hay có mô hình tương tranh tốt hơn liên quan đến tình huống này không?

+0

cũng là các nhóm bên ngoài được nhóm, bạn có kiểm soát được không? nó có vẻ đại diện cho một mục tiêu tốt để bắt đầu, bạn có thể viết dịch vụ web caching của riêng bạn caching web ở phía trước của nó –

+0

của nó không phải trong kiểm soát của tôi. Đó là một dịch vụ mà chúng tôi đang gọi từ một nhà cung cấp – Codemwnci

+0

Như trong mọi trường hợp _cache_: Có thực sự chắc chắn rằng dịch vụ đó là _really_ không quốc tịch? I E. dịch vụ "FetchCustomerDetailById" không thể lưu vào bộ nhớ cache vì một "ChangeCustomerName" trung gian sẽ phải làm mất hiệu lực bộ nhớ cache của bạn. –

Trả lời

6

Bạn có thể

  1. tính toán một băm mật mã được yêu cầu
  2. thấy nếu kết quả đã có trong cơ sở dữ liệu cho băm này, và nếu như vậy, trả lại
  3. cửa hàng băm trong cơ sở dữ liệu với trạng thái "đang chờ xử lý"
  4. gọi dịch vụ web và cập nhật hàng trong cơ sở dữ liệu với kết quả.

Ở bước 2, nếu băm đã có trong cơ sở dữ liệu, với trạng thái "đang chờ xử lý", bạn có thể thăm dò cơ sở dữ liệu mỗi X mili giây và cuối cùng trả về kết quả khi nó ở đó.

The devil là tại các chi tiết, tất nhiên, bởi vì bạn sẽ phải quyết định những gì bạn làm trong trường hợp xảy ra lỗi:

  • bạn trả về một lỗi cho tất cả các yêu cầu giống hệt nhau tiếp theo?
  • bạn có làm cho các chuỗi đang chờ thử lại gọi dịch vụ web không?
  • bạn có trả lại lỗi không, nhưng chỉ trong một thời gian và sau đó thử lại?
+0

@downvoters: chăm sóc để giải thích các downvotes của bạn? –

+0

Tôi cũng muốn hiểu các downvotes. 2 phiếu bầu (một mỏ), 2 xuống, nhưng không có lời giải thích? Có điều gì xấu về giải pháp của bạn trên @ fyr's? – Codemwnci

+0

IIUC, giải pháp của fyr là có một bộ đệm cho mỗi máy chủ, và để tránh có một cơ sở dữ liệu vì đó là một điểm lỗi duy nhất. Tôi giả định rằng bạn đã có một cơ sở dữ liệu trung tâm, vì 99,9% các ứng dụng có sẵn. Vì vậy, tôi thiết kế một giải pháp mà tất cả các máy chủ sử dụng cơ sở dữ liệu trung tâm này như là một bộ nhớ cache liên tục. –

2

1.) Dịch vụ này đang chạy trên nhiều máy chủ web cho High Availability và khả năng mở rộng

Treat này chỉ đơn giản như thiết kế hạn chế. Điều này có nghĩa là không kết hợp tên máy chủ trong phương pháp tra cứu bộ nhớ cache của bạn. Miễn là kết quả không phụ thuộc vào máy chủ, bạn sẽ không có vấn đề gì. Tôi sẽ coi nó là một lỗ hổng thiết kế nếu hostA trả về một cái gì đó khác với hostB trong một môi trường HA với cùng một dịch vụ và các tham số giống nhau.

Nếu bạn muốn giữ cho hệ thống dự phòng, bạn không nên có bộ nhớ đệm trung tâm. Bởi vì hầu hết các lần một giải pháp "trung tâm" là một từ đồng nghĩa với "Điểm duy nhất của thất bại" - giải pháp. Khóa cũng phức tạp hơn nếu bạn đồng bộ hóa qua các máy chủ Ứng dụng.

Số lượng bộ nhớ cache bạn giới thiệu phụ thuộc một chút vào tốc độ truy cập bộ nhớ cache và tài nguyên bạn có sẵn trên hệ thống của mình. Giải pháp đơn giản nhất là lưu vào bộ nhớ cache trên mỗi cấp độ dịch vụ.

2.) Yêu cầu có thể mất tối đa 5 giây để trả lời, nhưng trong thời gian chờ đợi, Tôi có thể đã nhận được 2 hoặc 3 yêu cầu giống hệt khác.

Đây cũng là hạn chế về thiết kế. Bạn chia bộ nhớ đệm của mình chỉ bằng 2 bước khác nhau.

  1. Đầu tiên chèn một chìa khóa cho yêu cầu giống hệt của bạn nếu thread đầu tiên đi vào thói quen bộ nhớ đệm và truy cập khóa để giá trị của nó
  2. Chèn giá trị sau khi xử lý xong và miễn phí khóa

Bạn cũng cần để xử lý xử lý ngoại lệ.

Các lockingconnection cơ chế có thể được thực hiện với các chiến lược khác nhau

  • Synchronous - bạn chỉ cần thực hiện một Mutex/Semaphore hoặc bất cứ điều gì và truy cập khóa để phần quan trọng. Điều này có thể kết thúc có một số yêu cầu trong trạng thái chờ cho đến khi khóa biến mất
  • Không đồng bộ - bạn thực hiện một số loại cơ chế bỏ phiếu sẽ dẫn đến thông báo cho biết dữ liệu chưa sẵn sàng nếu chuỗi đáp ứng phần bị khóa (như trong quá trình xử lý đồng bộ). Điều này sẽ không dẫn đến nhiều kết nối mở nhưng giới thiệu phức tạp hơn.

Các Mutex/Semaphore hoặc bất cứ cấu trúc bạn sử dụng để khóa truy cập vào các phần quan trọng có thể phụ thuộc vào độc đáo chính (miễn là bạn không muốn để serialize quyền truy cập vào dịch vụ của bạn), bạn tính cho giống hệt nhau yêu cầu.

+0

hoàn toàn, tất cả máy chủ sẽ trả về giống nhau. Chúng chỉ được tách ra trên các nút khác nhau cho HA/Khả năng mở rộng. Nhưng ràng buộc nó tạo ra là chúng ta không còn trong một miền nối tiếp, mà là miền xử lý song song. Vì vậy, bạn đang đề xuất một bộ nhớ đệm trung tâm, có thể truy cập bởi tất cả các nút sử dụng cơ chế khóa – Codemwnci

+0

proxy bộ nhớ đệm phải ở trước bộ cân bằng tải; nếu bạn cho phép vượt qua một yêu cầu, bạn cũng có thể để cho nó chạy hơn là chỉ giữ nó chờ đợi trên một nút –

+0

@Codemwnci Tôi đã điều chỉnh bài đăng của mình cho câu hỏi này. – fyr