使用 Memcached 缓存 Doctrine 结果
Doctrine Result caching with Memcached
我刚刚安装了 Memcached,我正在尝试使用它来缓存使用 Doctrine ORM(Doctrine 2.4.8+、Symfony 2.8+)完成的各种查询的结果。
我的 app/config/config_prod.yml
有这个:
doctrine:
orm:
metadata_cache_driver: memcached
result_cache_driver: memcached
query_cache_driver: memcached
并且我尝试 useResultCache()
处理 2 个这样的查询(我只是在此处替换了缓存 ID 作为示例):return $query->useResultCache(true, 300, "my_cache_id")->getArrayResult();
。这里有特殊查询,因为它们是本机查询 (SQL),因为它们的复杂性,但该方法可用于任何查询 (class AbstractQuery),所以我认为它应该有效。
不幸的是,事实并非如此。每次我刷新页面时,如果我只是在数据库中进行了更改,则会显示更改。我检查了 memcached 的统计数据,似乎仍然有一些缓存命中,但我真的不知道如何,cf。我刚才说的。
有没有人知道为什么这里似乎没有使用缓存来获取假定的缓存结果?我是不是误解了什么,TTL 被忽略了?
没有生成错误,memcached 日志为空。
根据@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();
因此,似乎由于某种原因,Doctrine 未能成功获取 ResultCacheDriver。我试图在 useResultCache()
之前设置它,但我有一个来自 Memcached 的异常:Error: Call to a member function get() on null
。
我决定通过调用 Memcached() 更直接地完成它。我想我会根据我的需要在控制器和存储库中做这种事情。经过一些测试,它完美地工作。
这是我基本上做的:
$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
}
我可能会把它放在服务中。还不确定这种东西的 "best practice" 是什么。
编辑:我做了一个服务。但它只适用于原生sql...所以问题仍未解决
Edit²:我找到了一个关于这个空问题的有效解决方案(意味着它找不到 Memcached)。代码位:
$memcached = new \Memcached();
$memcached->addServer('localhost', 11211);
$doctrineMemcached = new \Doctrine\Common\Cache\MemcachedCache();
$doctrineMemcached->setMemcached($memcached);
$query
->setResultCacheDriver($doctrineMemcached)
->useResultCache(true, 300);
现在,我想知道我应该在 config_prod.yml
中放入哪些内容才能使用 useResultCache()
函数。
我刚刚安装了 Memcached,我正在尝试使用它来缓存使用 Doctrine ORM(Doctrine 2.4.8+、Symfony 2.8+)完成的各种查询的结果。
我的 app/config/config_prod.yml
有这个:
doctrine:
orm:
metadata_cache_driver: memcached
result_cache_driver: memcached
query_cache_driver: memcached
并且我尝试 useResultCache()
处理 2 个这样的查询(我只是在此处替换了缓存 ID 作为示例):return $query->useResultCache(true, 300, "my_cache_id")->getArrayResult();
。这里有特殊查询,因为它们是本机查询 (SQL),因为它们的复杂性,但该方法可用于任何查询 (class AbstractQuery),所以我认为它应该有效。
不幸的是,事实并非如此。每次我刷新页面时,如果我只是在数据库中进行了更改,则会显示更改。我检查了 memcached 的统计数据,似乎仍然有一些缓存命中,但我真的不知道如何,cf。我刚才说的。
有没有人知道为什么这里似乎没有使用缓存来获取假定的缓存结果?我是不是误解了什么,TTL 被忽略了?
没有生成错误,memcached 日志为空。
根据@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();
因此,似乎由于某种原因,Doctrine 未能成功获取 ResultCacheDriver。我试图在 useResultCache()
之前设置它,但我有一个来自 Memcached 的异常:Error: Call to a member function get() on null
。
我决定通过调用 Memcached() 更直接地完成它。我想我会根据我的需要在控制器和存储库中做这种事情。经过一些测试,它完美地工作。
这是我基本上做的:
$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
}
我可能会把它放在服务中。还不确定这种东西的 "best practice" 是什么。
编辑:我做了一个服务。但它只适用于原生sql...所以问题仍未解决
Edit²:我找到了一个关于这个空问题的有效解决方案(意味着它找不到 Memcached)。代码位:
$memcached = new \Memcached();
$memcached->addServer('localhost', 11211);
$doctrineMemcached = new \Doctrine\Common\Cache\MemcachedCache();
$doctrineMemcached->setMemcached($memcached);
$query
->setResultCacheDriver($doctrineMemcached)
->useResultCache(true, 300);
现在,我想知道我应该在 config_prod.yml
中放入哪些内容才能使用 useResultCache()
函数。