【发布时间】:2020-11-14 18:40:59
【问题描述】:
作为示例,用户执行一些更新操作,需要一起执行三个操作: 更新数据库、发送电子邮件和向其他服务执行网络请求。发送电子邮件和执行网络请求是非事务性的,如果一个失败而另一个成功,我们最终会处于不正确的状态。有处理这种情况的通用模式吗?
【问题讨论】:
标签: database transactions
作为示例,用户执行一些更新操作,需要一起执行三个操作: 更新数据库、发送电子邮件和向其他服务执行网络请求。发送电子邮件和执行网络请求是非事务性的,如果一个失败而另一个成功,我们最终会处于不正确的状态。有处理这种情况的通用模式吗?
【问题讨论】:
标签: database transactions
对我有用的一种常见模式是创建一个电子邮件表作为电子邮件队列,可以轻松地将插入到该表的内容包含在事务中。
如果我们从外部进程获得成功响应,则有另一个进程读取此电子邮件表并向外部进程(smtp 服务器、sendgrid...)发送请求并将电子邮件标记为“已发送”。如果失败,电子邮件不会被标记为“已发送”并且可以重试。可能会出现电子邮件发送成功但网络出现错误导致响应失败的情况,重试可能会发送重复的电子邮件,但这种情况很少见,应该不会导致问题。
您还可以查看类似模式的数据库电子邮件:https://docs.microsoft.com/en-us/sql/relational-databases/database-mail/database-mail?view=sql-server-ver15
我们可以进一步扩展这个模式,用同样的想法发送网络请求。你可以看看这个https://microservices.io/patterns/data/transactional-outbox.html
【讨论】: