我正在实现一个CQRS模式,其中一个或多个进程将记录插入到数据库中,并且一个或多个进程以不同的速度拉动它们。
我希望消费者流程在数据库中轮询自上次检查后插入的新记录,但我不确定如何(安全地)实现此目的。
您可以假设插入后行不会更改。似乎每行都没有足够的唯一ID,以及表示插入时间的时间戳。
如果我查询时间戳大于我看到的最后一行的记录,那么如果同时插入多个记录(具有相同的时间戳),我会遇到问题。
如果我查询id大于我看到的最后一行的记录,那么我遇到了并发事务可能以非递增顺序提交ID的问题(例如,postgreSQL会话提前分配和缓存序列ID以提高性能)
理想情况下,我正在寻找与DBMS无关的解决方案,并且能够尽可能接近实时地使用数据。有什么想法吗?
澄清:每个消费者应该多次使用每一行。这意味着,仅仅因为一个消费者处理一行不应该阻止其他消费者这样做。每个消费者都会使用相同的数据做一些不同的事情。
答案 0 :(得分:0)
由于您有大量数据进入并且上一个时间戳可能有多个记录,因此您需要一种方法来跟踪读取的数据。以下是一些不同的方法,包括它们的优点和缺点:
MAX(timestamp)
来执行此操作,这样您就可以获得表中的所有数据,除了数据可能仍会进入的最后一个数据。Pro:简单设计
骗局:不是实时处理
(timestamp = lasttimestamp and id not in (set of ids)) or timestamp > lasttimestamp)
亲:几乎是实时
Con:需要额外存储空间
答案 1 :(得分:0)
如果您不使用分片或类似内容:
您可以使用乐观锁定。
为此,您可以创建order
列,在记录表(日志)上使用唯一索引。在每次插入之前,生产者向Log查询最大order
,它会递增它并插入带有此order
的下一条记录。
如果发生并发异常(即Duplicate entry '12345' for key order
),则重试整个过程(查询,增量,插入)。
如果您使用分片或类似内容:
然后,您将需要一个额外的服务/表,每次要求它生成一个新的,唯一的,始终增加的order
整数。
这样做的缺点是必须管理另一个部分,一个必须高度可用的单点故障。
P.S。