多个 pod/微服务更新/插入同一条记录

Posted

技术标签:

【中文标题】多个 pod/微服务更新/插入同一条记录【英文标题】:Multiple pods/micro-services update/insert the same record 【发布时间】:2021-09-26 14:15:00 【问题描述】:

我有多个服务都接收请求 示例请求有 3 个字段 - 货币、日期、金额

现有表有 2 个条目

密钥、货币、日期、金额

123,美元,8 月 1 日,100

234,欧元,12 月 1 日,50

插入盒

如果表中不存在具有接收到的货币、日期组合的条目,则插入一个新条目。 例如对于上表,如果我们收到 (USD, 2 Aug, 20),将插入新条目

更新案例

如果表中已存在接收货币的条目,则通过更新“金额”字段来更新日期组合现有条目 例如对于上表,如果我们收到(USD,8 月 1 日,30 日),现有条目将更新 123,更新后的金额将为 100+30 = 130

场景问题

在 kubernetes/类似平台上运行的服务有 3 个实例,并且以下三个服务大约在同一时间接收请求 第一项服务收到请求(美元,9 月 1 日,100) 第二个服务收到请求(美元,9 月 1 日,200) 第三个服务收到请求(美元,9 月 1 日,300)

理想情况应该是,无论哪个服务先处理,都会创建第一个插入条目,其余两个服务将更新该条目的数量

期望的最终结果:

美元,9 月 1 日,600

但是,观察到的结果之一是,在 2 个服务最终插入记录的情况下,根据应用层处理,第三个条目可能会失败,因为它找不到唯一条目来更新金额,或者它最终更新基于数据库的返回条目之一

美元,9 月 1 日,100

美元,9 月 1 日,500

问题

应该如何以及在哪里处理?在数据库中使用锁还是在Java应用层?

【问题讨论】:

2 个服务如何最终插入记录?您的数据库没有唯一约束吗? 目前没有唯一约束。那么,如果添加了唯一约束,对于上述情况,在(货币,日期)上,那么可以防止插入吗?此外,尝试插入记录的其他服务将失败,因为该条目已由第一个服务插入。这种情况下,如何重试更新记录 【参考方案1】:

这似乎是一个并发问题,我想你正在做两个查询来做到这一点。首先,您尝试在数据库中查找记录,其次,您根据它是否存在进行更新或插入。 但是,如果两个请求同时(或几乎同时)到达,则两个请求会进行第一次查询,并且由于该货币不存在,因此它们会执行插入操作。

为了解决这个问题,我将按照 Kayaman 的建议在货币中添加一个唯一约束,并将查询更改为 upsert(它是某些数据库支持的更新和插入查询的组合)以进行查询原子的,所以如果插入失败,因为已经有相同货币的记录,它将进行更新

这里是关于如何在 Postgresql 中进行 upsert 的文档 https://www.postgresqltutorial.com/postgresql-upsert/

【讨论】:

以上是关于多个 pod/微服务更新/插入同一条记录的主要内容,如果未能解决你的问题,请参考以下文章

多个Azure应用程序,在同一群集上具有与版本无关的通用微服务

在同一个 kubernetes 集群中从一个 pod 调用一个 rest api 到另一个 pod

什么是微服务上下文中的边车?

springCloud进阶(微服务架构&Eureka)

微服务架构中的数据库位置

如何连接不同的微服务应用?