有没有一种方法可以基于SQL查询锁定块执行



背景:我有一个迷你聊天应用程序,可以让你为许多对话者创建聊天室。给定对话者集合的聊天室只能创建一次,因此,如果创建具有相同对话者集合聊天室的请求将执行两次,则必须只创建一个聊天室:

所以:

  • 用于对话者1和对话者2的HTTP POST/聊天室->创建聊天室
  • 用于对话者1和对话者2的HTTP POST/聊天室->跳过创建文件室,因为已存在

基本上,这是一种简单的多对多关系,有三个表:聊天室、聊天室对话者和对话者

当使用单线程环境时,一切似乎都可以,然而,在多线程上,我最终会为同一组对话者创建重复的聊天室。这似乎是一个经典的并发问题,可以通过锁定机制来解决,但是,当两个或多个微服务实例可用时,应该将锁定委派给数据库级别。

因为我使用的是Spring Boot,所以我尝试过使用@Lock(LockModeType.PESSIMISTIC_READ)然而,在JPA查询中,第二个线程没有挂在查询上,而是创建了重复的聊天室。查询如下:

select c.chat_id from chat c
join chat_interlocutor c1 on  c1.chat_id = c.chat_id and c1.interlocutor_id = ?1
join chat_interlocutor c2 on c2.chat_id = c.chat_id and c2.interlocutor_id = ?2

整个场景如下:

微服务1

  1. 检查两个对话者之间是否存在聊天(对话者1和对话者2(
  2. 它不存在,所以创建它

Microservice2

  1. 检查两个对话者之间是否存在聊天(对话者1和对话者2(,[此处微服务1尚未提交]
  2. 它不存在,所以创建它[这里我们正在创建重复的聊天室]

最简单的解决方案是在数据库中使用一个唯一的聊天室id作为同步机制(在微服务之间共享(。

要做到这一点,您必须在会话开始时创建一个聊天室实体。您必须确保它始终使用由2名参与者确定的唯一ID创建。如果创建成功,那么这是一个新的聊天室,如果存在唯一密钥冲突,那么聊天室已经存在。

你描述的流程几乎是正确的,但你错过了在微服务构建的具有唯一id的数据库中创建聊天室。你仍然需要检查聊天室是否已经存在,因为这样可以避免太多的冲突。

最新更新