如何在 Cosmos DB 中实现发件箱模式

How to implement outbox pattern in Cosmos DB

我希望在 Cosmos DB 中实现对发件箱模式的支持。

但是,Cosmos DB 似乎不支持跨集合的事务。

那我该怎么做呢?

我一直在考虑几种实现方法:

使用服务总线事务

Service bus transaction scope 内,发送消息(尚未提交),执行 Cosmos DB 更新,如果成功,我们将提交服务总线事务以使消息可供订阅者使用。

使用触发器在发件箱集合中插入行

当 inserts/updates 发生时,我们使用 Cosmos DB 触发器将相应的消息插入发件箱 table,从那时起,一切照常进行。

使用触发器执行 azure 函数

创建Azure functions as Cosmos DB triggers。我几乎喜欢这个,但直接向服务总线发送消息会好得多。

使用数据泵

添加两个字段 UpdateTimestampOutboxMessageTimestamp。当记录更新时 UpdateTimestamp.

某些进程会查找这两个不匹配的记录,并为每个创建通知消息并将其转发到相应的队列或主题。

当然,然后它会更新第二个时间戳以使它们匹配。

关于如何做到这一点的其他想法?

通常,您将东西存储在您的 cosmos db 集合中。然后你有更改提要将这些更改发送给一些观察者(假设是 azure 函数)。然后你的 azure 函数可以做任何事情:将它放入其他消费者的队列中,保存到另一个不同投影的集合中,等等......在你的 azure 函数中你应该为与函数运行时无关的故障实现你的死信队列(例如, 由于 id 冲突,写入另一个集合失败)

[更新]

让我再补充一点作为对您评论的回应。 根据我的经验,在分布式系统中以原子方式做事归结为:

  1. 始终按照相同的顺序做事
  2. 使第二步有效(确保您可以重复多次以获得相同的结果)
  3. 一旦第一步成功 - 重复第二步直到成功

因此,如果您想发送有关保存到 cosmos db 中的内容的电子邮件,您可以:

  1. 在 cosmos db 中保存记录
  2. 让 azure 函数监听变化提要
  3. 收到插入的文档后 > 发送电子邮件(更强大的解决方案实际上会将其放入队列中,一些专门的消费者从中发送电子邮件)

另一种方法是将初始命令(保存记录)放入队列,然后有 2 个消费者(一个用于保存,一个用于发送电子邮件)但是你有一个订购问题(如果这对你很重要) .