我正在制作一个网站,我认为用一个宁静的架构(至少不是与这个问题相关的部分)来实现它没有意义,但它会导致共享数据库的多个服务器之间的竞争条件出现一些问题。
我的网站有关于另一个产品的用户的信息,所以它有一个用户表(虽然不是我网站的用户)。用户有很多文件。
用户和文件由自动化服务填充,而不是在站点上手动填充。该服务将文件发布到服务器,服务器解析它们并从文件中获取用户名。如果用户名是新的,它会在表中创建一个新的用户行。然后它将有关文件的信息返回给发出请求的服务。
我看到的问题是当多个请求同时进入相关对象的竞争条件时,它会导致诸如违反数据库中的唯一索引之类的事情。
例如,用户名上有一个唯一键。如果自动服务对来自同一用户的文件的 2 个请求同时进入,则此代码可能会出现问题。
var myuser = db.users.FirstOrDefault(u => u.username == username);
if(myuser == null)
{
myuser = new user(username);
db.AddObject(user);
}
db.SaveChanges();
请求 1 将看到没有用户名为 foo 的用户,因此 if 条件返回 true。请求 2 看到同样的事情,不知道请求 1 已经开始创建用户,当请求 2 尝试保存时,它违反了唯一密钥。
这个问题有共同的模式或解决方案吗?我知道如果服务器是 RESTful 的,这不会是一个问题,但我不认为服务改变它发出请求的方式真的可行,所以如果可能的话,我希望保持不变。现在,它只是将文件发布到服务器,不知道该文件的用户是否已经存在,或者该文件是否已发布到服务器(它可能会多次发布)。如果这些对象尚不存在,则创建这些对象,如果存在,则更新项目列表。但就服务而言,它只是想知道有关文件的某些信息,而不关心它是否已经存在于我的数据库中。
我认为尝试通过请求创建用户,然后尝试通过请求创建文件,然后在另一个请求中请求有关文件的信息,这太慢了。此外,该服务通过 Parallel.ForEach 一次运行多个请求,如果在单个线程中运行它会太慢。