Microservices: cách xử lý các mối quan hệ khóa ngoài


85

Kiến trúc microservices đề xuất rằng mỗi dịch vụ nên xử lý dữ liệu của chính nó. Do đó, bất kỳ dịch vụ nào (Dịch vụ A) phụ thuộc vào dữ liệu thuộc sở hữu của dịch vụ khác (dịch vụ B) phải truy cập dữ liệu đó không phải bằng cách thực hiện các cuộc gọi DB trực tiếp mà thông qua api được cung cấp bởi dịch vụ thứ hai (dịch vụ B).

Vì vậy, các phương pháp hay nhất của microservices đề xuất về việc kiểm tra các ràng buộc khóa ngoại.

Ví dụ: Tôi đang phát triển tính năng giao hàng (microservice 1) cho các sản phẩm và một số sản phẩm nhất định chỉ có thể phân phối đến một số địa điểm nhất định như đã đề cập trong bảng sản phẩm mà chỉ các sản phẩm dịch vụ vi mô (mircoservice 2) mới có thể truy cập được.

Làm cách nào để đảm bảo rằng microservice 1 (tức là tính năng giao hàng) không đưa đơn đặt hàng đến một địa điểm chưa được xác nhận. Tôi có câu hỏi này vì tính năng giao hàng không thể truy cập trực tiếp vào cơ sở dữ liệu sản phẩm, vì vậy không có ràng buộc nào áp dụng ở cấp DB khi đơn đặt hàng được đặt vào cơ sở dữ liệu giao hàng (không thể kiểm tra xem liệu khớp khóa ngoại có tồn tại trong cơ sở dữ liệu sản phẩm hay không hoặc bảng).

Câu trả lời:


71

Có thể sử dụng cơ sở dữ liệu dùng chung cho nhiều dịch vụ nhỏ. Bạn có thể tìm thấy các mẫu quản lý dữ liệu của microservices trong liên kết này: http://microservices.io/patterns/data/database-per-service.html . Nhân tiện, nó là một blog rất hữu ích cho kiến ​​trúc microservices.

Trong trường hợp của bạn, bạn thích sử dụng cơ sở dữ liệu cho mỗi mẫu dịch vụ. Điều này làm cho các microservices tự chủ hơn. Trong trường hợp này, bạn nên sao chép một số dữ liệu của mình giữa nhiều dịch vụ nhỏ. Bạn có thể chia sẻ dữ liệu bằng các cuộc gọi api giữa các microservices hoặc bạn có thể chia sẻ nó với tính năng nhắn tin không đồng bộ. Nó phụ thuộc vào cơ sở hạ tầng của bạn và tần suất thay đổi dữ liệu. Nếu nó không thay đổi thường xuyên, bạn nên sao chép dữ liệu với các sự kiện không đồng bộ.

Trong ví dụ của bạn, Dịch vụ giao hàng có thể trùng lặp địa điểm giao hàng và thông tin sản phẩm. Dịch vụ sản phẩm quản lý các sản phẩm và địa điểm. Sau đó, dữ liệu yêu cầu được sao chép vào cơ sở dữ liệu của dịch vụ Delivery với các thông báo không đồng bộ (ví dụ: bạn có thể sử dụng Rabbit mq hoặc apache kafka). Dịch vụ giao hàng không thay đổi sản phẩm và dữ liệu vị trí nhưng nó sử dụng dữ liệu khi thực hiện công việc của mình. Nếu một phần dữ liệu sản phẩm được sử dụng bởi Dịch vụ giao hàng thường xuyên thay đổi, thì việc sao chép dữ liệu với nhắn tin không đồng bộ sẽ rất tốn kém. Trong trường hợp này, bạn nên thực hiện các cuộc gọi api giữa Sản phẩm và Dịch vụ giao hàng. Dịch vụ giao hàng yêu cầu Dịch vụ sản phẩm kiểm tra xem sản phẩm có thể phân phối đến một địa điểm cụ thể hay không. Dịch vụ giao hàng yêu cầu dịch vụ Sản phẩm với số nhận dạng (tên, id, v.v.) của sản phẩm và vị trí. Các số nhận dạng này có thể được lấy từ người dùng cuối hoặc được chia sẻ giữa các microservices. Vì cơ sở dữ liệu của các microservices ở đây khác nhau, chúng tôi không thể xác định các khóa ngoại giữa dữ liệu của các microservices này.

Các cuộc gọi Api có thể dễ thực hiện hơn nhưng chi phí mạng cao hơn trong tùy chọn này. Ngoài ra, các dịch vụ của bạn cũng ít tự chủ hơn khi bạn thực hiện các cuộc gọi api. Bởi vì, trong ví dụ của bạn khi Dịch vụ sản phẩm không hoạt động, Dịch vụ giao hàng không thể thực hiện công việc của mình. Nếu bạn sao chép dữ liệu với thông báo không đồng bộ, dữ liệu cần thiết để thực hiện phân phối sẽ nằm trong cơ sở dữ liệu của dịch vụ phân phối. Khi Dịch vụ sản phẩm không hoạt động, bạn sẽ có thể giao hàng.


1
Câu trả lời chính xác. Tôi sử dụng lệnh gọi API, nhưng nó cũng cần phân loại và phân trang dữ liệu từ một dịch vụ khác. Bạn có biết cách tiếp cận tốt nhất cho trường hợp đó không?
tranceholic

5
Bạn nên thêm các tham số liên quan đến phân trang và sắp xếp vào api của mình. Sau đó, trách nhiệm của việc lấy đúng trang với thứ tự phù hợp sẽ do người tiêu dùng của api đảm nhận. Có một số công nghệ được sử dụng để xác định một api như GraphQL. Theo như tôi biết, những công nghệ đó đã có các tính năng sắp xếp và phân trang. Nếu bạn không sử dụng loại công nghệ này, bạn có thể chỉ cần lấy các thông số từ ứng dụng khách của mình và sử dụng chúng để trả về dữ liệu được sắp xếp theo các trang.
Ali Sağlam

Câu trả lời tuyệt vời thực sự!
TS

2
Tuy nhiên, bạn có giữ khóa ngoại không? Ví dụ: Mỗi bài đăng trên blog sẽ có nhiều bình luận. Monolith sẽ có bảng nhận xét với khóa ngoại cho bài đăng trên blog. Tuy nhiên trong microservice, chúng ta sẽ có hai dịch vụ. Dịch vụ 1: Đăng Microservie với các trường bảng này (PostID, Tên, Nội dung) Dịch vụ 2: Nhận xét Microservie với các trường bảng này (CommentID, PostID, Cpmment) Câu hỏi đặt ra là, chúng ta có cần "PostID" trong dịch vụ 2 (Comments Microservice) không? Tôi đoán câu trả lời là có, vì chúng ta cần biết nhận xét nào thuộc về bài đăng nào. Tôi hiểu có đúng không?
rakesh mehra

1
Làm thế nào để phân chia một hệ thống thành các microservice hoàn toàn là một câu chuyện khác, nhưng nếu bạn quyết định tạo 2 microservices như bài đăng và bình luận, bạn cần mã định danh bài đăng trên các bình luận microservice vì mỗi bình luận thuộc một bài đăng. Tuy nhiên, nó không có nghĩa là bạn cần xác định FK giữa các bảng đó. FK chỉ là một hạn chế trong thế giới RDBMS giúp đảm bảo tính toàn vẹn và nhất quán của dữ liệu. Nếu bạn giữ dữ liệu của microservice này trên các lược đồ riêng biệt, bạn không thể xác định FK hoặc thậm chí bạn có thể giữ dữ liệu của một người trên nosql db (điều này có ý nghĩa đối với nhận xét microservice) trong đó FK không được áp dụng.
Ali Sağlam

24

Khi phân phối mã của bạn để đạt được sự kết hợp giảm, bạn muốn tránh chia sẻ tài nguyên và dữ liệu là tài nguyên bạn muốn tránh chia sẻ.

Một điểm khác là chỉ một thành phần trong hệ thống của bạn sở hữu dữ liệu (cho các hoạt động thay đổi trạng thái), các thành phần khác có thể ĐỌC nhưng KHÔNG ĐƯỢC VIẾT, chúng có thể có bản sao của dữ liệu hoặc bạn có thể chia sẻ một mô hình xem mà chúng có thể sử dụng để có được trạng thái mới nhất của một đối tượng.

Việc giới thiệu tính toàn vẹn tham chiếu sẽ giới thiệu lại khớp nối, thay vì bạn muốn sử dụng thứ gì đó như Guids cho khóa chính của mình, chúng sẽ được tạo bởi người tạo đối tượng, phần còn lại là quản lý tính nhất quán cuối cùng.

Hãy xem bài nói chuyện của Udi Dahan tại NDC Oslo để biết thêm chi tiết

Hi vọng điêu nay co ich


2
Liên kết cho bài nói chuyện của Udi Dahan rất thú vị
Comencau 23/03/18

3

giải pháp đầu tiên: Thành phần API

 Implement a query by defining an API Composer, which invoking the
 services that own the data and performs an in-memory join of the
 results

nhập mô tả hình ảnh ở đây

giải pháp thứ hai: CQRS

Define a view database, which is a read-only replica that is designed to support that 
query. The application keeps the replica up to data by subscribing to Domain events 
published by the service that own the data.

nhập mô tả hình ảnh ở đây


1

Bản cập nhật năm 2020 cho câu trả lời này là sử dụng công cụ Chụp dữ liệu thay đổi như Debezium. Debezium sẽ theo dõi các bảng cơ sở dữ liệu của bạn để tìm các thay đổi và truyền chúng đến Kafka / Pulsar (các đường ống khác) và người đăng ký của bạn sau đó có thể nắm bắt các thay đổi và đồng bộ hóa chúng.

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.