2009-02-24 16 views
9

Tôi phải gửi email, ghi vào một tập tin và gọi một dịch vụ web. Để duy trì tính nhất quán, tất cả các bước phải xảy ra. Nếu bất kỳ bước nào ném ra một ngoại lệ hoặc lỗi, tất cả các bước phải được khôi phục.Các mẫu để thực hiện các giao dịch bên ngoài cơ sở dữ liệu

Trước khi tôi chuyển động cơ ACID đối tượng của riêng mình, có bất kỳ mẫu được chấp nhận phổ biến nào để triển khai ngữ nghĩa ACID ở cấp đối tượng không?

Tốt hơn, có bất kỳ thư viện hiện có nào tôi có thể sử dụng cho nền tảng .NET không?

Chỉnh sửa: Tôi biết việc gửi email không thể hoàn tác được nhưng không kết nối được với máy chủ SMTP là nguyên nhân gây ra toàn bộ giao dịch. Ngoài ra, tôi muốn điều này được mở rộng để sử dụng với các hành động trong tương lai.

+0

Làm cách nào để bạn quay lại email? – mbeckish

+0

có thể gửi hồi âm :) –

+0

Lệnh rút lại sẽ hoạt động. Về lý thuyết, tôi có thể nhổ nó ra khỏi máy chủ Exchange như thể nó không bao giờ xảy ra, nhưng điều đó có thể bị cá. –

Trả lời

5

Lần cuối cùng tôi thấy điều gì đó như thế này là vài năm trước. Một chút mà tôi nhớ về nó là nó đang sử dụng mẫu lệnh và lưu trữ từng đối tượng lệnh trong một hàng đợi. Tôi nghĩ rằng đó là một ngăn xếp LIFO.

Vì vậy, nếu "giao dịch" không thành công, công cụ sẽ bật ra một đối tượng lệnh, hoàn tác lệnh, sau đó hủy đối tượng lệnh. Lặp lại cho đến khi ngăn xếp trống. Ngăn xếp đã bị xóa nếu "giao dịch" thành công.

Thật không may, tôi không nhớ nhiều hơn thế.

CSLA.NET thực hiện ngăn xếp hoàn tác tương tự. Đó là ví dụ duy nhất với mã mà tôi có thể nghĩ ra khỏi đỉnh đầu.

3

Windows Workflow Foundation có khái niệm là compensation (sử dụng hoạt động Hỗn hợp) khi ngữ nghĩa ACID có thể không phù hợp ..Tất nhiên, nó cũng hỗ trợ cho các giao dịch ACID.

Một câu hỏi hay là tại sao phải bận tâm với bồi thường ? Không phải là một giao dịch ACID lớn với tự động quay lại cũng tốt không? Giao dịch ACID là thích hợp nhất khi hoạt động xảy ra trong cùng một cơ sở dữ liệu hoặc trong hệ thống thông tin tương tự . Nó cũng là thích hợp nhất khi hoạt động kết thúc nhanh chóng . Khi các công ty khác nhau và các dịch vụ có liên quan, xác định quy trình về ngữ nghĩa ACID thường là thách thức. Vì nó là bị cô lập và bền, bạn phải giữ tất cả tài nguyên của các công ty khác nhau bị khóa trong suốt thời gian thực hiện tác vụ. Điều này thường xuyên không hợp lý, đặc biệt nếu tác vụ kéo dài. Đối với nó để nhất quán và nguyên tử, bạn cần mã quảng cáo đặc biệt.

1

Vì bạn không thể bỏ gửi e-mail, và nó tương đối rẻ tiền để viết một tập tin, tôi chỉ muốn làm những điều theo thứ tự thích hợp:

  1. Hãy thử để ghi các file/ghi tệp. Nếu không thành công, hãy dừng, nếu không hãy tiếp tục:
  2. Gọi dịch vụ web.Nếu không thành công, hãy xóa tệp và dừng, nếu không hãy tiếp tục:
  3. Gửi e-mail - email không đồng bộ dù sao, vì vậy bạn sẽ không bao giờ thực sự biết nó đã được gửi hay chưa vì hầu hết các máy chủ e-mail được đặt lại để thử lại trong một vài ngày nếu xảy ra lỗi và bạn không bao giờ lấy lại một xác nhận rằng e-mail đã đi qua ngay cả khi nó thành công.
+0

Bạn vẫn có thể gặp sự cố nếu dịch vụ web nhận và xử lý cuộc gọi nhưng phản hồi bị mất. Tôi chạy vào cuộc gọi này với cuộc gọi AddItem của eBay, có tác dụng phụ không thể đảo ngược của việc tiêu tiền. –

+0

Trong thế giới mạng, không bao giờ nhận được ACK giống như một NACK, phải không? Khi điều này xảy ra, thường thì một số can thiệp thủ công là cần thiết và không thể tránh khỏi. –

3

Kỹ thuật đơn giản nhất mà không cần dựa nhiều vào thư viện bên ngoài là prevalence. Định kỳ điểm kiểm tra bằng cách sử dụng serialization để chụp nhanh trạng thái của bạn, sau đó duy trì journal bằng cách tuần tự hóa đủ thông tin về mọi hoạt động có hiệu lực bên cạnh dữ liệu của bạn để lặp lại sau. Nếu một cái gì đó thổi lên, hãy tải lại trạm kiểm soát gần đây nhất, sau đó áp dụng lại tất cả các bản ghi tạp chí được viết sau thời điểm đó.

Để điều gì đó tinh vi hơn, hãy thử software transactional memory. Nó có thể là hơi vụng về để thực hiện trong các ngôn ngữ hiện tại, nhưng là khá mạnh mẽ và có thể cung cấp cho bạn một số kỹ thuật đồng thời bổ sung là tốt.

Đối với các hoạt động không thể đảo ngược như truy cập dịch vụ web hoặc gửi email, bạn cần sử dụng compensating transactions: thực hiện cuộc gọi dịch vụ web khác để hủy hoặc cập nhật kết quả trước đó hoặc gửi email khác tư vấn cho người nhận mọi thứ không hoạt động như dự định.

0

Hai suy nghĩ:

  • Như Jeffrey Hantin đề cập, software transactional memory (STM) là khá ngọt ngào. Hãy xem cách nó được triển khai/sử dụng trong Clojure; Rich Hickey's videos thật ấn tượng.
  • Một khía cạnh quan trọng của Command pattern của danh tiếng GoF là "không thể xóa". Một thực hiện của điều này có thể đun sôi xuống để đề nghị đơn giản (nhưng dù sao hữu ích) bởi Robert C. Barth
1

Một ý tưởng là sử dụng JMS là 'động cơ' và bạn có thể sử dụng các giao dịch JMS (mà có thể tham gia giao dịch hiện có ví dụ Giao dịch DB). Điều này bắt đầu dẫn đến một kiến ​​trúc hướng sự kiện không đồng bộ mà có lẽ là một điều tốt trừ khi chúng ta đang nói các ứng dụng đơn giản - trong trường hợp đó bạn có thể không cần phải đặt câu hỏi.

Ví dụ về điều này sẽ là tạo tài khoản đơn giản. Đối với điều này bạn muốn duy trì thông tin tài khoản cho DB và cũng gửi cho người dùng một email để kích hoạt - nhưng bạn muốn họ trong cùng một giao dịch vì lý do rõ ràng.

Bạn không nên đặt mã gửi email trong giao dịch bởi vì ngay cả khi bạn có thể gửi email - giao dịch cam kết có thể không thành công vì một lý do nào đó. Bạn cũng không nên đặt email gửi bên ngoài giao dịch (sau khi cam kết) vì gửi email có thể không dẫn đến tài khoản mồ côi.

Vì vậy, để sử dụng JMS trong trường hợp này - hãy đặt mã gửi JMS trong giao dịch DB và yêu cầu nó tham gia giao dịch đó. Bạn được đảm bảo gửi tin nhắn. Ở đầu bên kia có cái gì đó tiêu thụ hàng đợi gửi email ra ngoài. Trong trường hợp gửi email thất bại, tùy chọn tốt nhất là đăng nhập/nâng cao cảnh báo - JMS sẽ quay lại và đưa thông điệp trở lại hàng đợi để sử dụng sau này. tức là để thử và gửi lại email sau khi bạn đã hy vọng sửa bất kỳ vấn đề nào.

Điều quan trọng là - bản ghi DB nhất quán và email cuối cùng được gửi đi.

0

Ngoài ra, dự án thử nghiệm STM .NET vừa được phát hành. Dự án này thêm bộ nhớ giao dịch vào C#. Nó thực sự sửa đổi CLR để hỗ trợ điều này.