Tìm nguồn cung ứng sự kiện, phát lại và phiên bản


8

Tôi đang thiết kế một hệ thống sử dụng Nguồn sự kiện, CQRS và microservice. Tôi sẽ hiểu rằng đây không phải là một mô hình không phổ biến. Một tính năng chính của dịch vụ cần là khả năng bù nước / khôi phục từ hệ thống hồ sơ. Microservice sẽ tạo ra các lệnh và truy vấn trên MQ (Kafka). Các dịch vụ siêu nhỏ khác sẽ đáp ứng (sự kiện). Các lệnh và truy vấn sẽ được duy trì trên S3 cho mục đích kiểm toán và khôi phục.

Quá trình suy nghĩ hiện tại là, với mục đích khôi phục hệ thống, chúng tôi có thể trích xuất nhật ký sự kiện từ S3 và chỉ cần đưa nó trở lại vào Kafka.

Tuy nhiên, điều này không thừa nhận những thay đổi ở cả người sản xuất người tiêu dùng theo thời gian. Phiên bản ở cấp lệnh / truy vấn dường như có cách nào đó để giải quyết vấn đề nhưng tôi không thể quấn lấy người tiêu dùng phiên bản để tôi có thể thực thi rằng khi một lệnh, trong quá trình khôi phục, được nhận và xử lý, thì chính xác là như vậy [phiên bản của mã] đang thực hiện xử lý vì đây là lần đầu tiên nhận được lệnh.

Có bất kỳ mô hình nào tôi có thể sử dụng để giải quyết điều này? Có ai biết các hệ thống khác quảng cáo tính năng này không?

EDIT: Thêm một ví dụ.

Một 'người mua' gửi 'câu hỏi' cho 'người bán' trên trang web đấu giá của tôi. Dòng chảy trông như sau: UI -> Web App: POST /question {:text text :to seller-id :from user-id} Web App -> MQ: SEND {:command send-question :args [text seller-id user-id]} MQ -< Audit: <command + args appended to log in S3> MQ -< Questions service: - Record question in DB - Email seller 'You have a question'

Bây giờ, do yêu cầu kinh doanh mới, tôi điều chỉnh người tiêu dùng 'Dịch vụ câu hỏi', để duy trì số lượng tất cả các câu hỏi chưa đọc. Lược đồ DB được thay đổi. Chúng tôi đã không có khái niệm về việc liệu người bán có đọc câu hỏi hay không, cho đến bây giờ. Dòng cuối cùng trở thành:

MQ -< Questions service: - Record question in DB - Email seller 'You have a question' - Increment 'unread questions count'

Hai lệnh là các vấn đề, một trước khi thay đổi, một sau khi thay đổi. 'Số câu hỏi chưa đọc' bằng 1.

Hệ thống gặp sự cố. Chúng tôi đã khôi phục bằng cách phát lại các lệnh thông qua mã mới . Vào cuối quá trình khôi phục, 'số câu hỏi chưa đọc' của chúng tôi bằng 2. Mặc dù, trong ví dụ giả định này, kết quả không phải là một thảm họa, trạng thái đã được khôi phục không giống như trước đây.


Câu hỏi dường như trộn lẫn một vài mối quan tâm. Tìm nguồn cung ứng sự kiện là một chiến lược kiến ​​trúc để đối phó với các hệ thống có nhiều thay đổi đối với dữ liệu cơ bản đang diễn ra. Phiên bản DTO và sao lưu và dữ liệu là một vấn đề khác hoàn toàn. Tìm nguồn cung ứng sự kiện không được thiết kế đặc biệt để giúp bạn có khả năng khôi phục kim loại trần - vì điều đó, bạn cần phải có một chiến lược cụ thể.
Người chơi

Có lẽ việc phát sóng sự kiện có thể giải quyết vấn đề của bạn: blog.trifork.com/2012/04/17/iêu
Songo

@ rmayer06 Tôi nghĩ một ví dụ là những gì tôi đang theo đuổi!
Rừng Antony

Câu trả lời:


16

Đầu tiên, điều quan trọng là phải hiểu và có thể tận dụng sự khác biệt giữa các LệnhSự kiện.

Như câu hỏi này ngắn gọn chỉ ra, Lệnh là những điều chúng ta muốn xảy ra và Sự kiện là những điều đã xảy ra. Một lệnh không nhất thiết dẫn đến một sự kiện quan trọng trong hệ thống, nhưng nó thường làm. Ví dụ: một send messagelệnh có thể bị từ chối, trong trường hợp không có sự kiện nào xảy ra (thông thường, một lỗi sẽ không được coi là một sự kiện theo nghĩa này, mặc dù chúng ta vẫn có thể chọn đăng nhập nó trong nhật ký chẩn đoán). Bây giờ, nếu send messagelệnh được chấp nhận, message sentsự kiện xảy ra và chi tiết sự kiện có thể mô tả người gửi, người nhận và nội dung.

Khi chúng ta nói về trạng thái hệ thống, chúng ta thực sự đang thảo luận không phải là đỉnh cao của các lệnh, mà là các sự kiện. Chỉ các sự kiện có thể gây ra sự thay đổi trạng thái trong hệ thống. Để rút ra từ một ví dụ cuộc sống, giả sử tôi đi đến siêu thị Publix địa phương và mua vé số Florida. Lệnh là "Mua vé" và sự kiện là "Vé được phát hành". Lệnh tiếp theo của tôi sau đó là xổ số để rút số của tôi cho PowerBall. Xổ số sẽ bỏ qua lệnh của tôi (nhưng tôi không có kiến ​​thức) và sự kiện "Số PowerBall được chọn" diễn ra bất kể mong muốn của tôi. Nếu số của tôi trùng khớp, sự kiện "Jackpot won" xảy ra với tôi (và tôi nghĩ rằng lệnh của tôi đã được nghe). Nếu không, tôi nhận ra lệnh của tôi đã bị bỏ qua.

Từ góc độ lịch sử, xổ số chỉ quan tâm đến một tập hợp các sự kiện. Xổ số chỉ quan tâm rằng (a) một vé đã được phát hành, (b) các số được chọn và (c) giải độc đắc đã giành được. Đó là những mục quan tâm. Hành động mua vé, muốn giành chiến thắng, v.v ... đều không liên quan, như những gì tôi làm với vé sau khi tôi thua. Mặc dù thế giới thực thay đổi đối với các sự kiện trần tục, chúng ta chỉ cần ghi lại những sự kiện có ý nghĩa đối với hệ thống của chúng ta.

Về lý thuyết, theo một kỹ thuật tìm nguồn cung ứng sự kiện, một luồng các sự kiện có thể được phát lại từ đầu thời gian để đến trạng thái hiện tại. Điều này phụ thuộc vào giả định rằng các điều kiện hệ thống cơ bản là không đổi và xác định. Tuy nhiên, những giả định này không hợp lệ trong nhiều hệ thống. Dữ liệu liên quan đến một sự kiện, cũng như các loại sự kiện chúng ta quan tâm, có thể thay đổi khi phần mềm máy tính của chúng tôi phát triển. Ngoài ra, nó có thể tốn kém về mặt tính toán để tính lại trạng thái hiện tại để đáp ứng với mọi truy vấn. Vì lý do này, ảnh chụp nhanh của trạng thái hệ thống thường được thực hiện để thể hiện các điểm đã biết theo thời gian, mà hầu hết các sự kiện gần đây có thể được thêm vào.

Mặc dù vẫn có thể phát lại luồng sự kiện trên nhiều phiên bản, nhưng số lượng nỗ lực của con người liên quan đến việc này có thể bị cấm chi phí. Trừ khi có một lý do chính đáng để thiết kế khả năng đó vào hệ thống, tốt hơn hết là bạn nên xây dựng hệ thống của mình để sử dụng ảnh chụp nhanh.

Ví dụ trong câu hỏi

Trong ví dụ được đưa ra trong câu hỏi, kiến ​​trúc không thực sự dựa trên sự kiện; nó dựa trên lệnh. Phát lại các lệnh tạo trạng thái hệ thống. Đây là một mô hình chống và nên được sửa chữa. Thay vào đó, các sự kiện chính là:

  • Người mua đặt câu hỏi
  • Người bán trả lời câu hỏi

Mỗi sự kiện này có thể được "phát lại" để đưa ra trạng thái hiện tại. Ví dụ: trong hành động đặt câu hỏi, hành vi hệ thống có thể là gửi email cho người bán và tăng bộ unanswered questionđếm. Hành vi này có thể được thay đổi; tuy nhiên, thực tế là câu hỏi đã được hỏi thì không. Tương tự, hệ thống có thể giảm số unanswered questionlượng truy cập khi người bán phản hồi. Hành vi này có thể thay đổi, nhưng thực tế là người bán phản hồi thì không.

Hầu hết các hệ thống tìm nguồn cung ứng sự kiện sẽ tự động tính toán số lượng câu hỏi chưa được trả lời bằng cách phát lại luồng sự kiện cụ thể để trả lời một truy vấn.


Đây là một câu trả lời tuyệt vời, cảm ơn @ rmayer06
Antony Woods

Trong ví dụ xổ số này, bạn nói rằng "Chỉ các sự kiện có thể gây ra thay đổi trạng thái trong hệ thống", nhưng nếu sự kiện là "vé được phát hành" (và có lẽ sự kiện bao gồm một số chi tiết như dấu thời gian, người mua_id, Ticket_id), bạn sẽ làm thế nào ghi lại số tham chiếu của vé nếu không có hệ thống hồ sơ nào khác tạo ra id? Có một hệ thống CRUD truyền thống cần sản xuất vé trước khi nguồn sự kiện có thể ghi lại sự thật là thì quá khứ không?
Homan

Hành động phát hành vé sự kiện trong trường hợp này. Dữ liệu liên quan đến sự kiện là những gì đang được mô tả là sự kiện trong câu hỏi của bạn, rất hữu ích nhưng về mặt kỹ thuật không chính xác. Hơn nữa, các sự kiện thường đại diện cho một tổng thể các chi tiết, trong đó chúng có thể được sáng tác và phân tách tương đối vô hạn theo mỗi hướng.
Người chơi

Uh ... bạn đã thổi vào tâm trí của tôi với những điều tổng thể.
Homan

Tôi đoán những gì tôi đã suy nghĩ là thế này: Trong thế giới CRUD, đặc biệt là Rails, việc có id tự động tăng cho các khóa chính của bảng là điều phổ biến. Chúng tôi tạo hồ sơ mà không biết id, DB trao lại cho tôi id vé. Bây giờ chuyển sang thế giới Tìm nguồn sự kiện, từ những gì tôi đã đọc, sự kiện được 'hiện thực hóa' trước khi nó được duy trì trong DB và nó yêu cầu một id tổng hợp. Vì vậy, thay vì lấy lại id sau khi kiên trì từ DB, có vẻ như id duy nhất phải được biết đến để có thể mô tả toàn bộ. Điều đó có vẻ như chúng ta nên luôn luôn tạo ra uuid và không tự động id.
Homan

3

Các lệnh và truy vấn sẽ được duy trì trên S3 cho mục đích kiểm toán và khôi phục.

Để kiểm toán, chắc chắn. Để khôi phục ? Điều đó thật kỳ lạ và có thể khiến bạn đau đầu.

Nếu bạn định tìm nguồn cung ứng sự kiện, bạn muốn trạng thái bù nước từ các sự kiện (những điều đã xảy ra trong quá khứ) chứ không phải các lệnh. Điều này giúp bạn tránh khỏi hầu hết các vấn đề liên quan đến thay đổi khi thực hiện lệnh - bạn chỉ cần xử lý các thay đổi trạng thái liên tục.

Phiên bản vẫn là một mối quan tâm. Cụ thể, bạn muốn đảm bảo rằng các sự kiện được duy trì của bạn càng linh hoạt càng tốt (các biểu diễn DTO, thay vì tuần tự hóa trực tiếp các khái niệm trong miền của bạn). Khi đọc các sự kiện từ cửa hàng, bạn có cơ hội cập nhật chúng khi cần thiết trước khi áp dụng chúng vào trạng thái bù nước.


Ok, vì vậy tôi nghĩ lời khuyên của bạn là bớt lo lắng về việc khôi phục các lệnh và nhiều hơn về các sự kiện? Ví dụ: nếu tôi nhận được lệnh dọc theo dòng "thêm 10 hạt" thì sau đó tôi sẽ phát hành và lưu trữ một sự kiện có nội dung "10 hạt đậu đã được thêm vào. Tổng số mới: 40"?
Rừng Antony

Vâng đúng vậy. Mỗi thay đổi trạng thái trong thực thể có nguồn gốc sự kiện của bạn được thể hiện bằng một hoặc nhiều sự kiện; để bù nước, bạn phát lại tất cả các sự kiện đó theo thứ tự.
VoiceOfUnreason 16/2/2016

2
Tôi đã không chấp nhận câu trả lời này nhưng tôi muốn cảm ơn bạn vì sự đóng góp vì nó rất quan trọng trong việc sửa đổi sự hiểu biết của tôi. Tôi đã chọn câu trả lời của rmayer06 chỉ vì nó trực tiếp hơn, tròn hơn và hữu ích hơn với một số người chỉ cần truy cập câu hỏi này để có câu trả lời nhanh.
Rừng Antony
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.