我有一个函数,看起来像这样:
function findByAndCreateIfNotExists($criteria){
$entity = $this->findBy(['criteria'=>$criteria]);
// this is the problem area, if request 1 is still creating the entity, request 2 won't find it yet.
if (! $entity) {
$entity = $this->createEntity($criteria);
}
return $entity;
}
这个函数被各种请求使用,我发现并发请求有时会试图创建同一个实体,抛出一个DBALException
,抱怨唯一键的条目重复。
我已经考虑过这里提到的LOCK TABLES
:如何用doctrine2在symfony2中锁定整个表?
但鉴于条令中没有这样做的功能,我猜这不是首选的方法。我的问题是,如何防止并发请求试图创建同一个实体并始终返回正确的实体?
根据想法创建自己的锁定系统:
类似于:
function findByAndCreateIfNotExists($criteria){
$entity = $this->findBy(['criteria'=>$criteria]);
// this is the problem area, if request 1 is still creating the entity, request 2 won't find it yet.
$lockPath ='/tmp/'.md5($criteria).'.lock';
if (! $entity && !file_exists($lockPath)) {
$fh = fopen($lockPath, 'w') or die("Can't create file");
$entity = $this->createEntity($criteria);
unlink(($lockPath);
}
return $entity;
}
但从你所说的来看,我认为你做的方向不对,最好稍微重建一下应用程序架构,并将RabbitMQ队列作为中间点来服务你的请求