Tái cấu trúc các khối u từ một ảnh chụp nhanh trên màn hình của máy chiếu chứ không phải là Cửa hàng sự kiện


13

Vì vậy, tôi đã tán tỉnh Nguồn cung cấp sự kiện và CQRS một thời gian rồi, mặc dù tôi chưa bao giờ có cơ hội áp dụng các mô hình trên một dự án thực sự.

Tôi hiểu lợi ích của việc tách biệt mối quan tâm đọc và viết của bạn và tôi đánh giá cao cách Nguồn cung cấp sự kiện giúp dễ dàng dự kiến ​​các thay đổi trạng thái cho cơ sở dữ liệu "Mô hình đọc" khác với Cửa hàng sự kiện của bạn.

Điều tôi không rõ lắm là tại sao bạn lại bù nước cho các Tập hợp của mình từ Cửa hàng Sự kiện.

Nếu việc chiếu thay đổi cơ sở dữ liệu "đọc" quá dễ dàng, tại sao không phải luôn luôn thay đổi cơ sở dữ liệu "ghi" có lược đồ hoàn toàn khớp với mô hình miền của bạn? Đây có hiệu quả sẽ là một cơ sở dữ liệu ảnh chụp nhanh.

Tôi tưởng tượng điều này phải khá phổ biến trong các ứng dụng ES + CQRS trong tự nhiên.

Nếu đây là trường hợp, Cửa hàng sự kiện chỉ hữu ích khi xây dựng lại cơ sở dữ liệu "ghi" của bạn do thay đổi lược đồ? Hay tôi đang thiếu một cái gì đó lớn hơn?


Không có gì sai khi ghi không đồng bộ vào một cửa hàng trạng thái mô hình ghi và sử dụng riêng để tải các thực thể. Các vấn đề nhất quán chính xác tương tự có mặt cho dù bạn làm điều đó hay không. Chìa khóa để khắc phục các vấn đề nhất quán đó là mô hình hóa các thực thể của bạn khác nhau. Không có gì kỳ diệu về Nguồn cung cấp sự kiện giải quyết các vấn đề nhất quán đó. Sự kỳ diệu nằm trong mô hình và không quan tâm. Có những ứng dụng cụ thể đòi hỏi sự nhất quán ở cấp độ đó có các thực thể gây tranh cãi cao cho dù bạn mô hình hóa chúng như thế nào và sẽ cần sự chú ý đặc biệt bất kể.
Andrew Larsson

Miễn là bạn có thể đảm bảo giao hàng các sự kiện. Để làm điều này, ứng dụng của bạn chỉ cần xuất bản đồng bộ một sự kiện lên một xe buýt sự kiện bền. Sau khi xuất bản, công việc của ứng dụng đã hoàn tất. Sau đó, xe buýt sẽ giao nó cho nhiều người xử lý sự kiện khác nhau: một để cập nhật cửa hàng sự kiện, một để cập nhật cửa hàng nhà nước và bất kỳ ai khác cần để cập nhật các cửa hàng đọc. Lý do bạn đang sử dụng Tìm nguồn sự kiện là vì bạn không quan tâm đến tính nhất quán ngay lập tức nữa. Nắm lấy nó.
Andrew Larsson

Không có lý do gì bạn phải liên tục tải các thực thể của mình từ cửa hàng sự kiện. Đó không phải là mục đích của nó. Mục đích của nó là cung cấp một sổ cái thô, vĩnh viễn của tất cả mọi thứ đã xảy ra trong hệ thống. Các cửa hàng thực thể và các mô hình đọc không chuẩn hóa là để tải và đọc.
Andrew Larsson

Câu trả lời:


13

Điều tôi không rõ lắm là tại sao bạn lại bù nước cho các Tập hợp của mình từ Cửa hàng Sự kiện.

Bởi vì "sự kiện" là cuốn sách kỷ lục.

Nếu việc chiếu thay đổi cơ sở dữ liệu "đọc" quá dễ dàng, tại sao không phải luôn luôn thay đổi cơ sở dữ liệu "ghi" có lược đồ hoàn toàn khớp với mô hình miền của bạn? Đây có hiệu quả sẽ là một cơ sở dữ liệu ảnh chụp nhanh.

Đúng; đôi khi nó là một tối ưu hóa hiệu suất hữu ích để sử dụng một bản sao được lưu trong bộ nhớ cache của trạng thái tổng hợp, thay vì tạo lại trạng thái đó từ đầu mỗi lần. Hãy nhớ rằng: quy tắc tối ưu hóa hiệu suất đầu tiên là "Đừng". Nó tăng thêm độ phức tạp cho giải pháp và bạn muốn tránh điều đó cho đến khi bạn có động lực kinh doanh hấp dẫn.

Nếu đây là trường hợp, Cửa hàng sự kiện chỉ hữu ích khi xây dựng lại cơ sở dữ liệu "ghi" của bạn do thay đổi lược đồ? Hay tôi đang thiếu một cái gì đó lớn hơn?

Bạn đang thiếu một cái gì đó lớn hơn.

Điểm đầu tiên là nếu bạn đang xem xét một giải pháp có nguồn gốc sự kiện, đó là bởi vì bạn hy vọng sẽ có giá trị trong việc bảo tồn lịch sử của những gì đã xảy ra, nghĩa là bạn muốn thực hiện những thay đổi không mang tính hủy diệt .

Vì vậy, đó là lý do tại sao chúng tôi đang viết cho các cửa hàng sự kiện.

Đặc biệt, điều này có nghĩa là mọi thay đổi cần phải được ghi vào cửa hàng sự kiện.

Các nhà văn cạnh tranh có khả năng có thể phá hủy các bài viết của nhau hoặc đưa hệ thống đến trạng thái ngoài ý muốn, nếu họ không biết về các chỉnh sửa của nhau. Vì vậy, cách tiếp cận thông thường khi bạn cần sự nhất quán là giải quyết bài viết của bạn đến một vị trí cụ thể trong tạp chí (tương tự như PUT có điều kiện trong api HTTP). Một bài viết thất bại nói với người viết rằng sự hiểu biết hiện tại của họ về tạp chí không đồng bộ, và họ nên phục hồi.

Trở lại vị trí tốt đã biết sau đó phát lại bất kỳ sự kiện bổ sung nào vì thời điểm đó là một chiến lược phục hồi phổ biến. Vị trí tốt được biết đến đó có thể là bản sao của bộ đệm cục bộ hoặc đại diện trong cửa hàng ảnh chụp nhanh của bạn.

Trong đường dẫn hạnh phúc, bạn có thể giữ một ảnh chụp nhanh tổng hợp trong bộ nhớ; bạn chỉ cần tiếp cận với một cửa hàng bên ngoài khi không có bản sao địa phương.

Hơn nữa, bạn không cần phải hoàn toàn bị bắt kịp, nếu bạn có quyền truy cập vào sổ sách ghi chép.

Vì vậy, cách tiếp cận thông thường ( nếu sử dụng kho lưu trữ ảnh chụp nhanh) là duy trì nó không đồng bộ . Bằng cách đó, nếu bạn cần khôi phục, bạn có thể làm như vậy mà không cần tải lại và phát lại toàn bộ lịch sử của tổng hợp.

Có nhiều trường hợp sự phức tạp này không đáng quan tâm, bởi vì các tập hợp hạt mịn với vòng đời có phạm vi thường không thu thập đủ các sự kiện để lợi ích vượt quá chi phí duy trì bộ đệm ẩn.

Nhưng khi nó là công cụ phù hợp cho vấn đề, tải một biểu diễn cũ của tổng hợp vào mô hình ghi, sau đó cập nhật nó với các sự kiện bổ sung, là một điều hoàn toàn hợp lý để làm.


Tất cả điều này nghe có vẻ hợp lý. Khi tôi chơi xung quanh với một triển khai ES giả trước đây, tôi đã sử dụng EventStore để đảm bảo tính nhất quán nhưng tôi cũng đã viết một cách đồng bộ vào cái mà bạn gọi là "kho lưu trữ ảnh chụp nhanh". Điều này có nghĩa là trạng thái hiện tại luôn sẵn sàng để đọc mà không phải phát lại các sự kiện. Tôi nghi ngờ điều này sẽ không có quy mô tốt, nhưng vì nó chỉ là một bài tập mà tôi không bận tâm.
MetaFight

6

Vì bạn không chỉ định mục đích của cơ sở dữ liệu "ghi" sẽ là gì, tôi sẽ giả sử ở đây rằng ý của bạn là gì: khi đăng ký bản cập nhật mới cho tổng hợp, thay vì xây dựng lại tổng hợp từ cửa hàng sự kiện, bạn nâng nó từ cơ sở dữ liệu "ghi", xác nhận thay đổi và đưa ra một sự kiện.

Nếu đây là ý của bạn, thì chiến lược này sẽ tạo ra một điều kiện cho sự không nhất quán: nếu một bản cập nhật mới xảy ra trước khi bản cập nhật cuối cùng có cơ hội đưa nó vào cơ sở dữ liệu "ghi", bản cập nhật mới sẽ được xác nhận chống lại dữ liệu lỗi thời, do đó có khả năng phát hành một sự kiện "không thể" (tức là "không được phép") và làm hỏng trạng thái hệ thống.

Ví dụ, hãy xem xét một ví dụ thường trực về việc đặt chỗ trong một nhà hát. Để ngăn chặn đặt phòng đôi, bạn cần đảm bảo rằng chỗ ngồi đang được đặt chưa được thực hiện - đây là những gì bạn gọi là "xác nhận". Để làm điều đó, bạn lưu trữ một danh sách các ghế đã đặt trong cơ sở dữ liệu "ghi". Sau đó, khi có yêu cầu đặt phòng, bạn kiểm tra xem ghế được yêu cầu có trong danh sách hay không và nếu không, hãy đưa ra sự kiện "đã đặt", nếu không sẽ phản hồi với thông báo lỗi. Sau đó, bạn chạy một quy trình chiếu, trong đó bạn lắng nghe các sự kiện "đã đặt" và thêm các ghế đã đặt vào danh sách trong cơ sở dữ liệu "ghi".

Thông thường, hệ thống sẽ hoạt động như thế này:

1. Request to book seat #1
2. Check in the "already booked" list: the list is empty.
3. Issue a "booked seat #1" event.
4. Projection process catches the event, adds seat #1 to the "already booked" list.
5. Another request to book seat #1.
6. Check in the list: the list contains seat #1
7. Respond with an error message.

Tuy nhiên, điều gì sẽ xảy ra nếu các yêu cầu đến quá nhanh và bước 5 xảy ra trước bước 4?

1. Request to book seat #1
2. Check in the "already booked" list: the list is empty.
3. Issue a "booked seat #1" event.
4. Another request to book seat #1.
5. Check in the list: the list is still empty.
6. Issue another "booked seat #1" event.

Bây giờ bạn có hai sự kiện để đặt cùng một chỗ. Trạng thái hệ thống bị hỏng.

Để ngăn điều này xảy ra, bạn không bao giờ nên xác nhận các cập nhật đối với phép chiếu. Để xác thực bản cập nhật, bạn xây dựng lại tổng hợp từ cửa hàng sự kiện, sau đó xác thực bản cập nhật đối với bản cập nhật. Sau đó, bạn phát hành một sự kiện, nhưng sử dụng bộ bảo vệ dấu thời gian để đảm bảo rằng không có sự kiện mới nào được phát hành kể từ lần cuối bạn đọc từ cửa hàng. Nếu thất bại, bạn chỉ cần thử lại.

Xây dựng lại tổng hợp từ các cửa hàng sự kiện có thể mang một hình phạt hiệu suất. Để giảm thiểu điều này, bạn có thể lưu trữ các ảnh chụp nhanh tổng hợp ngay trong luồng sự kiện, được gắn thẻ ID của sự kiện mà ảnh chụp nhanh được tạo. Bằng cách này, bạn có thể xây dựng lại tổng hợp bằng cách tải ảnh chụp nhanh gần đây nhất và chỉ phát lại các sự kiện xảy ra sau nó, trái ngược với việc luôn phát lại toàn bộ luồng sự kiện từ đầu thời gian.


Cảm ơn câu trả lời của bạn (và xin lỗi vì mất quá nhiều thời gian để trả lời). Những gì bạn nói về việc xác nhận hợp lệ đối với cơ sở dữ liệu ghi không nhất thiết phải đúng. Như tôi đã đề cập trong một nhận xét khác, trong một ví dụ về triển khai ES tôi đang chơi với tôi đã đảm bảo cập nhật cơ sở dữ liệu ghi của mình một cách đồng bộ (và lưu trữ concurrencyId / dấu thời gian). Điều này cho phép tôi phát hiện các vi phạm đồng thời lạc quan mà không cần phải sẵn sàng từ EventStore. Cấp phép, ghi đồng bộ một mình không bảo vệ chống tham nhũng dữ liệu, nhưng tôi cũng đang thực hiện viết đơn truy cập (đơn luồng).
MetaFight

Vì vậy, tôi đã sắp xếp các vấn đề nhất quán của mình. Mặc dù, tôi cho rằng đây là chi phí của khả năng mở rộng.
MetaFight

Viết đồng bộ vào cơ sở dữ liệu ghi vẫn có nguy cơ tham nhũng: điều gì xảy ra nếu việc ghi vào cửa hàng sự kiện của bạn thành công, nhưng việc ghi vào cơ sở dữ liệu ghi của bạn không thành công?
Fyodor Soikin

1
Nếu đọc phép chiếu thất bại, nó sẽ chỉ thử lại cho đến khi thành công. Nếu nó gặp sự cố hoàn toàn, nó sẽ thức dậy và tiếp tục từ nơi nó bị rơi - nói cách khác, cũng thử lại. Hiệu ứng quan sát bên ngoài sẽ không khác gì nó chỉ chạy chậm một chút. Nếu phép chiếu liên tục thất bại và thất bại liên tục, điều đó có nghĩa là có lỗi trong đó và điều đó sẽ phải được sửa. Sau khi sửa, nó sẽ tiếp tục chạy từ trạng thái tốt cuối cùng. Nếu toàn bộ cơ sở dữ liệu đọc bị hỏng do lỗi, tôi sẽ chỉ xây dựng lại cơ sở dữ liệu từ đầu bằng cách sử dụng lịch sử sự kiện.
Fyodor Soikin

1
Không có dữ liệu nào bị mất, đó là điểm lớn. Dữ liệu có thể bị kẹt trong một hình dạng bất tiện (để đọc) trong một thời gian, nhưng nó không bao giờ bị mất.
Fyodor Soikin

3

Lý do chính là hiệu suất. Bạn có thể lưu trữ một ảnh chụp nhanh cho mỗi lần xác nhận (commit = các sự kiện được tạo bởi một lệnh duy nhất, thường chỉ có một sự kiện) nhưng điều này rất tốn kém. Cùng với ảnh chụp nhanh, bạn cũng cần lưu trữ cam kết, nếu không đó sẽ không phải là tìm nguồn cung ứng Sự kiện. Và tất cả điều này phải được thực hiện nguyên tử, tất cả hoặc không có gì. Câu hỏi của bạn chỉ hợp lệ nếu các cơ sở dữ liệu / bảng / bộ sưu tập riêng biệt được sử dụng (nếu không sẽ chính xác là tìm nguồn cung cấp Sự kiện), do đó bạn buộc phải sử dụng các giao dịch để đảm bảo tính nhất quán. Giao dịch không thể mở rộng. Luồng sự kiện chỉ nối thêm (cửa hàng Sự kiện) là mẹ của khả năng mở rộng.

Lý do thứ hai là đóng gói tổng hợp. Bạn cần phải bảo vệ nó. Điều này có nghĩa là Tổng hợp nên được tự do thay đổi đại diện nội bộ của mình bất cứ lúc nào. Nếu bạn lưu trữ nó và phụ thuộc nhiều vào nó thì bạn sẽ có một thời gian rất khó khăn với phiên bản, điều này chắc chắn sẽ xảy ra. Trong trường hợp khi bạn chỉ sử dụng ảnh chụp nhanh như một tối ưu hóa, khi thay đổi lược đồ, bạn chỉ cần bỏ qua các ảnh chụp nhanh đó ( đơn giản ? Tôi không thực sự nghĩ vậy; chúc may mắn xác định rằng lược đồ của Aggregate thay đổi - bao gồm tất cả các thực thể và các đối tượng giá trị lồng nhau - trong một cách hiệu quả và quản lý đó).


Khi lược đồ Tổng hợp của tôi thay đổi, sẽ không phải là vấn đề đơn giản khi phát lại các sự kiện của tôi để tạo cơ sở dữ liệu "ghi" cập nhật?
MetaFight

Vấn đề là phát hiện sự thay đổi đó. Một tập hợp có thể rất lớn, với nhiều tệp / lớp.
Constantin Galbenu

Tôi không hiểu Sự thay đổi sẽ xảy ra với một bản phát hành phần mềm. Bản phát hành có thể sẽ đi kèm với một kịch bản cơ sở dữ liệu để tạo lại cơ sở dữ liệu "ghi".
MetaFight

Đó là rất nhiều việc phải làm cho một kịch bản di chuyển. Trong khi nó chạy ứng dụng phải xuống.
Constantin Galbenu

@MetaFight nếu luồng rất lớn, sẽ mất rất nhiều thời gian để xây dựng lại lược đồ tổng hợp mới ... Tôi đang nghĩ đến một ảnh chụp nhanh là trạng thái của một phép chiếu trực tiếp có thể chạy trước khi phát hành tổng hợp mới lược đồ
Narvalex
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.