【发布时间】:2018-07-26 11:44:35
【问题描述】:
我正在实现CQRS 模式,其中一个或多个进程将记录插入数据库,而一个或多个进程以不同的速度提取它们。
我希望消费者进程轮询数据库以查找自上次检查以来插入的新记录,但我不确定如何(安全地)实现这一点。
您可以假设行一旦插入就不会改变。似乎每行只有一个唯一的 id 和一个指示插入时间的时间戳是不够的。
如果我查询时间戳大于我看到的最后一行的记录,那么如果同时插入多条记录(具有相同的时间戳),我就会遇到问题。
如果我查询 id 大于我看到的最后一行的记录,那么我会遇到并发事务可能以非递增顺序提交 ID 的问题(例如,postgreSQL 会话提前分配和缓存序列 ID 以提高性能) .
理想情况下,我正在寻找一种与 DBMS 无关的解决方案,并且能够尽可能接近实时地使用数据。有什么想法吗?
澄清:每一行应该被消费多次,每个消费者一次。意思是,仅仅因为一个消费者处理一行不应该阻止其他消费者这样做。每个消费者都会对相同的数据做不同的事情。
【问题讨论】:
-
因为你有多个消费者,你要么需要一种方法让他们拥有一个共享存储,以便能够弄清楚他们已经阅读和处理了什么。一种方法是通过在处理时更新某些列来维护源表上的内容。如果无法更改表结构,您可以创建一个新表或采用其他形式来维护每个消费者处理的记录,例如在内存中、新表或某个共享文件中。
-
@clinomaniac 我澄清了这个问题:每一行应该被多次消费,每个消费者一次。
-
这使事情变得更简单,因为您不需要消费者确定每一行是否已被处理。现在唯一的问题是每个消费者的独特性。如果时间戳不够唯一,一种非常简单的方法是始终获取不包括当前的数据(可以是相对的)。根据我的假设,这应该会有所帮助,即您不会在数据中获得较旧的时间戳。当消费者再次投票时,您将获得最后一个。基本上这意味着忽略过去 10 秒左右进入的数据以避免重复。
-
@clinomaniac 如问题中所述:如果同时提交两行,但您在上一个查询中只读取其中一个,那么下次运行查询时,您将错过第二个行。
-
您会得到 10 秒(或一定时间)前编写的所有内容。您可以一次读取多行。