在RabbitMQ消费者中使Doctrine ORM缓存失效 | Symfony2

3

我有一个使用oldsound/rabbitmq-bundle在symfony2应用程序中实现的rabbitmq-consumer。 该应用程序每次消费10条消息,并使用message-data中提供的过滤器从mysql-db收集数据,使用doctrine-querybuilder实现。 缓存系统是APC。 考虑到查询的简化代码,请参考下面:

$qb = $this->entityManager
    ->getRepository('My\Entity')
    ->createQueryBuilder();
$qb
    ->select('sum(this) as this, sum(that) as that')
    ->andWhere('field in (:values)')
    ->setParameter('values', $filterValues);
$result = $qb
    ->getQuery()
    ->setSingleResult();

这个查询针对不同的过滤器值返回了10次相同的数据。当消费者重新启动并消费下一批10条消息时,我再次得到10次不同的结果。我认为这可能是doctrine-cache造成的,并尝试像这样使缓存无效:

$qb = $this->entityManager
    ->getRepository('My\Entity')
    ->createQueryBuilder();
$qb
    ->select('sum(this) as this, sum(that) as that')
    ->andWhere('field in (:values)')
    ->setParameter('values', $filterValues);
$result = $qb
    ->getQuery()
    ->setResultCacheLifetime(0)
    ->setSingleResult();

但是没有效果。 我可以通过仅一次消费1个消息来解决此问题,但这会使我的应用程序减速到无法接受的程度。

有人可以给我指点正确的方向吗?

谢谢, jojo


1
我们也在使用oldsound,你能否尝试启动10个消费者,每个消费者一次只消费一条消息? - Francesco Panina
我认为你可以在查询中使用以下内容:setCacheable(bool),useResultCache(bool)。 - M. Ivanov
1个回答

0

问题最终归结于我的代码错误。我错误地认为每次消费消息后,消费者都会重新实例化。但事实并非如此!在我的查询服务中,我将某些查询的结果保存在类属性中。然后,代码就像这样:

<?php
if (null === $this->queryResult) {
    $this->doQuery();
} else {
    return $this->queryResult
}

所以,在第一条消息被消费后,doQuery()再也没有被执行过,直到消费者重新启动。我不得不在每次运行后重置类属性,这显然解决了我的问题。

教训是:当您让消费者在一个进程中消费多个消息时,请记住,消费者和所有使用的服务仅初始化一次,并跨消费的消息保持其状态。

感谢@Francesco Panina指导我正确方向。请原谅我回复晚了 :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接