2011-11-15 27 views
5

Tôi đang có câu hỏi liên quan đến cập nhật cho nhiều tập hợp trong một giao dịch sử dụng JOliver's Event Store. Theo tôi hiểu, mọi tập hợp đều phải có luồng sự kiện riêng. Bây giờ, trong khi nhiều trình xử lý lệnh sẽ chỉ tải một tổng hợp duy nhất và chỉ cập nhật tổng hợp đó (tức là lưu sự kiện cho những tập hợp đó), tôi có thể tưởng tượng rằng sẽ có các trình xử lý lệnh cần cập nhật nhiều tập hợp. Và tất nhiên, tôi muốn làm điều đó một cách giao dịch.Cập nhật nhiều tập hợp bằng cách sử dụng JOliver EventStore

Tuy nhiên, tôi không thấy cách tôi có thể làm điều đó với Cửa hàng sự kiện. Lưu trữ các sự kiện được thực hiện bằng cách gọi CommitChanges() trên luồng sự kiện. Nếu chúng tôi đang có nhiều tập hợp để cập nhật, sẽ có nhiều luồng sự kiện và do đó có nhiều cuộc gọi đến CommitChanges(). Cách duy nhất để thực hiện giao dịch đó là bọc nó trong một TransactionScope, nhưng điều đó không có ý nghĩa nhiều, vì công nghệ lưu trữ cơ bản có thể không hỗ trợ các giao dịch. Vì vậy, tôi kết thúc với mã này, mà chắc chắn là không phải những gì tôi đang tìm kiếm:

 Guid aggregateGuid1 = Guid.NewGuid(); 
     Guid aggregateGuid2 = Guid.NewGuid(); 
     Guid commitGuid = Guid.NewGuid(); 

     var stream = store.OpenStream(aggregateGuid1, 0, int.MaxValue); 
     stream.Add(new EventMessage() { Body = new MonitorDisabled { MonitorGuid = aggregateGuid1, User = "A" } }); 
     stream.CommitChanges(commitGuid); 

     stream = store.OpenStream(aggregateGuid2, 0, int.MaxValue); 
     stream.Add(new EventMessage() { Body = new MonitorEnabled { MonitorGuid = aggregateGuid2, User = "B" } }); 
     // Can't commit twice with the same commit id, what if fails after first one? No way for the store to know it had to write the second part of the commit. 
     stream.CommitChanges(commitGuid); 

này khiến tôi cảm thấy tôi là hoàn toàn thiếu một cái gì đó về cách thức tổ chức sự kiện Store nên được sử dụng. Ai có thể giúp tôi ở đây? Cảm ơn rất nhiều!

Trả lời

3

Tôi không thể nói cho John Oliver, nhưng tôi nghĩ câu trả lời là "không". Tổng hợp là ranh giới giao dịch. Nếu bạn cần phối hợp cam kết của một số tập hợp, bạn cần một quá trình phối hợp rõ ràng, giống như một câu chuyện, điều đó sẽ làm và nếu cần thiết, hãy hoàn tác các sự kiện có liên quan.

+0

Bây giờ, giả sử chúng ta đang ở trong lưu trữ doanh nghiệp và chúng tôi đang quản lý các máy chủ trong các phòng ở các trung tâm dữ liệu. Và mỗi máy chủ được giám sát bởi một bộ màn hình, chúng ta hãy gọi đó là một cấu hình màn hình. Bây giờ, chúng tôi muốn vô hiệu hóa màn hình trong quá trình bảo trì. Và, chúng tôi có thể thực hiện bảo trì trên máy chủ, giá đỡ, phòng hoặc trung tâm dữ liệu hoàn chỉnh. Cấu hình màn hình là một tổng hợp tự nhiên cho màn hình cho một máy chủ, chúng tôi muốn nâng cao sự kiện MonitorDisabled trên tổng hợp cấu hình màn hình khi chúng tôi đặt một rack trong bảo trì. Chúng ta xác định ranh giới TX ở đâu? Máy chủ, giá, phòng, ...? – Jochen

+3

Nếu bạn có ranh giới phiên mã vượt qua ranh giới tổng hợp, bạn đang làm sai. Theo định nghĩa, tổng hợp là ranh giới giao dịch và mô hình của bạn nên phản ánh điều đó. –

8

Tổng hợp xác định ranh giới giao dịch.

Nếu bạn cần thực hiện giao dịch tổng hợp, bạn nên xem xét tổng hợp của mình và có thể thiết kế lại chúng.

Trong trường hợp thao tác (lệnh) ảnh hưởng nhiều hơn một tập hợp, và bạn chắc chắn rằng tập hợp của bạn được thiết kế tốt và ánh xạ tới ranh giới nhất quán thực trong miền của bạn, eventual consitency có thể là những gì bạn đang tìm kiếm. Chỉ cần gửi một lệnh cho mỗi tổng hợp, và có hai giao dịch, một cho mỗi người trong số họ. Nếu bạn không cảm thấy sự nhất quán cuối cùng là đúng cho trường hợp của bạn hơn tôi sợ nó trở lại bảng vẽ.

+0

Hmm, chúng ta hãy lấy một ví dụ cổ điển: giao dịch ngân hàng. Tài khoản là tổng hợp và tôi phải chuyển tiền từ tài khoản này sang tài khoản khác. Điều này có nghĩa là tôi phải lưu trữ một sự kiện như MoneySent trên một tài khoản và một sự kiện MoneyReceived trên tài khoản khác. Điều này đường nối một kịch bản hợp pháp cho một bản cập nhật giao dịch trên 2 tập hợp với tôi. Tôi đang thiếu gì? – Jochen

+0

Một số đọc thêm cho tôi biết trường hợp này nên được thực hiện bằng cách sử dụng các hành động bù trừ. Tôi sẽ phải đọc thêm về điều đó. Việc có thể viết một giao dịch trên 2 tập hợp có vẻ là một giải pháp sạch hơn nhiều (khi bạn kiểm soát cả hai tài khoản trong miền của mình). – Jochen

+0

Với DDD và ES/CQRS bạn sẽ đạt được một cái gì đó và mất một cái gì đó. Đó là [Định lý CAP] (http://en.wikipedia.org/wiki/CAP_theorem) Bạn có được phân vùng, khả năng mở rộng, tính khả dụng cao, v.v., nhưng bạn mất tính nhất quán. Vâng, bạn không thực sự mất nó, bạn chỉ nhận được nó bị trì hoãn. Giả sử lợi nhuận thừa cân những tổn thất bạn còn lại với việc tìm kiếm các giải pháp cho các trường hợp như bạn mô tả, và như bạn đã phát hiện ra thường có các giải pháp thường được chấp nhận như các hành động đền bù. –

0

Đôi khi có thể dễ dàng tận dụng lợi thế của các giao dịch phân tán trong các tình huống này nếu cơ sở hạ tầng của bạn hỗ trợ chúng.

TransactionScope với EventStore:

Các EventStore theo mặc định ngăn chặn bất kỳ giao dịch xung quanh tạo bởi NServiceBus trước khi cam kết thay đổi đối với cơ sở dữ liệu. Tuy nhiên nếu bạn đang sử dụng hàng đợi và cơ sở dữ liệu hỗ trợ phân phối giao dịch (MSMQ, SQL Server, Raven v.v.) thì bạn có thể thay đổi TransactionStcope'sptionOption thành Bắt buộc. Điều này sẽ đảm bảo rằng EventStore sẽ mở rộng trong giao dịch môi trường xung quanh, trong đó sẽ được phân phối bằng MSDTC và hàng đợi tin nhắn và cơ sở dữ liệu sẽ được giữ đồng bộ. - NES Documentation

giao dịch tài liệu chéo với RavenDB:

Bạn sẽ cạy giao dịch từ chết, lạnh, tay bị gãy của tôi - Ayende

Các vấn đề liên quan