简体   繁体   English

使用 Memcached 缓存 Doctrine 结果

[英]Doctrine Result caching with Memcached

I've just installed Memcached and i'm trying to use it to cache results of various queries done with Doctrine ORM (Doctrine 2.4.8+, Symfony 2.8+).我刚刚安装了 Memcached,我正在尝试使用它来缓存使用 Doctrine ORM(Doctrine 2.4.8+,Symfony 2.8+)完成的各种查询的结果。
My app/config/config_prod.yml have this :我的app/config/config_prod.yml有这个:

doctrine:
    orm:
        metadata_cache_driver: memcached
        result_cache_driver: memcached
        query_cache_driver: memcached  

And i tried to useResultCache() on 2 queries like that (i just replaced the cache id here for the example) : return $query->useResultCache(true, 300, "my_cache_id")->getArrayResult();我尝试在 2 个这样的查询上使用结果useResultCache() (我只是在示例中替换了缓存 ID): return $query->useResultCache(true, 300, "my_cache_id")->getArrayResult(); . . Special queries here because they're native queries (SQL) due to their complexity, but the method is available for any query ( class AbstractQuery ) so i assume it should work.这里的特殊查询是因为它们是本机查询 (SQL),因为它们很复杂,但该方法可用于任何查询( AbstractQuery 类),所以我认为它应该可以工作。
Unfortunately, it doesn't.不幸的是,事实并非如此。 Everytime i refresh the page, if i just did a change in the database, the change is displayed.每次刷新页面时,如果我只是在数据库中进行了更改,则会显示更改。 I've checked the stats of memcached and it seems there're still some cache hits but i don't really know how, cf.我检查了 memcached 的统计数据,似乎仍然有一些缓存命中,但我真的不知道如何,参见。 what i just said.我刚才说的。

Does anyone has an idea on why the cache doesn't seem to be used here to get the supposedly cached results ?有没有人知道为什么这里似乎没有使用缓存来获取所谓的缓存结果? Did i misunderstand something and the TTL is ignored somehow ?我是否误解了某些东西并且以某种方式忽略了 TTL?
There's no error generated, memcached log is empty.没有产生错误,memcached 日志是空的。

As requested by @nifr, here is the layout of my code to create the 2 native queries i put a Memcached test on :根据@nifr 的要求,这里是我的代码布局,用于创建我对 Memcached 测试进行的 2 个本机查询:

    $rsm = new ResultSetMapping;
    $rsm->addEntityResult('my_entity_user', 'u');
    // some $rsm->addFieldResult('u', 'column', 'field');
    // some $rsm->addScalarResult('column', 'alias');

    $sqlQuery = 'SELECT
        ... 
        FROM ...
        INNER JOIN ... ON ...
        INNER JOIN ... ON ...
        // some more join
        WHERE condition1
            AND condition2';
    // some conditions added depending on params passed to this function
    $sqlQuery .= '
            AND (fieldX = (subrequest1))
            AND (fieldY = (subrequest2))
            AND condition3
            AND condition4
        GROUP BY ...
        ORDER BY ...
        LIMIT :nbPerPage
        OFFSET :offset
        ';

    $query =
        $this->_em->createNativeQuery($sqlQuery, $rsm)
        // some ->setParameter('param', value)
        ;

    return $query->useResultCache(true, 300, "my_cache_id")->getArrayResult();

So, it seems for some reason Doctrine doesn't succeed to get the ResultCacheDriver.因此,似乎出于某种原因,Doctrine 无法成功获取 ResultCacheDriver。 I tried to set it before the useResultCache() but i had an exception from Memcached : Error: Call to a member function get() on null .我试图在useResultCache()之前设置它,但我有一个来自 Memcached 的异常: Error: Call to a member function get() on null

I've decided to do it more directly by calling Memcached().我决定通过调用 Memcached() 来更直接地做到这一点。 I guess i'll do this kind of stuff in controllers and repositories, depending on my needs.我想我会根据我的需要在控制器和存储库中做这种事情。 After some tests it works perfectly.经过一些测试,它完美地工作。
Here is what i basically do :这是我的主要工作:

    $cacheHit = false;
    $cacheId = md5("my_cache_id"); // Generate an hash for your cache id
    // We check if Memcached exists, if it's not installed in dev environment for instance
    if (class_exists('Memcached'))
    {
        $cache = new \Memcached();
        $cache->addServer('localhost', 11211);
        $cacheContent = $cache->get($cacheId);
        // We check if the content is already cached
        if ($cacheContent != false)
        {
            // Content cached, that's a cache hit
            $content = $cacheContent;
            $cacheHit = true;
        }
    }
    // No cache hit ? We do our stuff and set the cache content for future requests
    if ($cacheHit == false)
    {
        // Do the stuff you want to cache here and put it in a variable, $content for instance
        if (class_exists('Memcached') and $cacheHit == false) $cache->set($cacheId, $content, time() + 600); // Here cache will expire in 600 seconds
    }  

I'll probably put this in a Service.我可能会把它放在一个服务中。 Not sure yet what's the "best practice" for this kind of stuff.尚不确定这种东西的“最佳实践”是什么。

Edit : I did a service.编辑:我做了一个服务。 But it only works with native sql... So the problem stays unsolved.但它只适用于本机 sql ......所以问题仍未解决。
Edit² : I've found a working solution about this null issue (meaning it couldn't find Memcached).编辑²:我找到了有关此空问题的有效解决方案(意味着它找不到 Memcached)。 The bit of code :代码位:

        $memcached = new \Memcached();
        $memcached->addServer('localhost', 11211);
        $doctrineMemcached = new \Doctrine\Common\Cache\MemcachedCache();
        $doctrineMemcached->setMemcached($memcached);
        $query
            ->setResultCacheDriver($doctrineMemcached)
            ->useResultCache(true, 300);  

Now, i would like to know which stuff should i put in the config_prod.yml to just use the useResultCache() function.现在,我想知道我应该在config_prod.yml放入哪些内容以仅使用useResultCache()函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM