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



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

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

那我该怎么做呢?

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

使用服务总线事务

在服务总线事务范围内,发送消息(尚未提交),执行 Cosmos DB 更新,如果有效,则提交服务总线事务以使消息可供订阅者使用。

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

发生插入/更新时,我们使用 Cosmos DB 触发器将相应的消息插入到发件箱表中,从那时起,一切照旧。

使用触发器执行 Azure 函数

创建 Azure 函数作为 Cosmos DB 触发器。我几乎喜欢这个,但将消息直接发送到服务总线会好得多。

使用数据泵

添加两个字段UpdateTimestampOutboxMessageTimestamp。当记录更新时,UpdateTimestamp也会更新。

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

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

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

通常,将内容存储在 Cosmos DB 集合中。 然后,你让更改源将这些更改发送到某个观察者(假设 Azure 函数)。 然后,Azure 函数可以执行任何操作:将其放入其他使用者的队列中,保存到另一个以不同方式投影的集合中,等等... 在 Azure 函数中,应为与函数运行时无关的故障实现死信队列(例如, 由于 ID 冲突,写入另一个集合失败)

[更新]

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

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

因此,如果要在保存到 cosmos db 的内容上发送电子邮件,则可以:

  1. 将记录保存在宇宙数据库中
  2. 让 Azure 函数侦听更改源
  3. 收到插入的文档后>发送电子邮件(更强大的解决方案实际上会将其放入队列中,一些专门的消费者从中发送电子邮件)

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

最新更新