Usando o Doctrine Second Level Cache
Com o lançamento da versão 2.5 do Doctrine uma feature há muito esperada tornou-se estável o suficiente para uso. Trata-se do “Second Level Cache”, que segundo a documentação oficial foi projetada para reduzir a quantia de acessos a base de dados. Ele fica entre a aplicação e a base de dados para evitar o maior número possível de acessos ao banco.
Quando habilitado todas as entidades são primeiro pesquisadas no cache e caso não sejam encontradas são realizadas consultas e o valor da mesma fica em cache, para reduzir o acesso ao banco de dados nas próximas requisições.
O primeiro passo para usar o second level cache é ter certeza que estamos usando a versão 2.5 ou maior do Doctrine. Para isso alteramos nosso composer.json para algo parecido com:
{
"require": {
"doctrine/common": "2.5.*",
"doctrine/dbal": "2.5.*",
"doctrine/orm": "2.5.*"
}
}
Lembre-se de executar o composer update para atualizar o vendor do projeto.
Agora podemos habilitar o cache no bootstrap do projeto na criação do EntityManager.
// Enable second-level-cache
//pode ser qualquer outra forma de cache como Memcached, Xcache, etc
$cache = new \Doctrine\Common\Cache\ApcCache;
$cacheRegionConfiguration = new \Doctrine\ORM\Cache\RegionsConfiguration();
$factory = new \Doctrine\ORM\Cache\DefaultCacheFactory($cacheRegionConfiguration, $cache);
$config->setSecondLevelCacheEnabled();
$config->getSecondLevelCacheConfiguration()->setCacheFactory($factory);
O código completo pode ser visto nesse gist
O próximo passo é configurar nossas entidades para que elas façam uso do cache. Podemos escolher um dos modos de cache disponíveis:
- READ_ONLY, o valor padrão. Permite que as entidades em cache sejam apenas lidas e não modificadas. É a forma mais performática mas é útil apenas para entidades que são apenas para leitura
- NONSTRICT_READ_WRITE. Permite que as entidades possam ser alteradas mas não possui controle de “lock”.
- READ_WRITE. O modo mais completo, permite alterações e faz um controle mais seguro do acesso as entidades evitando conflitos. Mas para isso perde um pouco da performance e o sistema de cache selecionado precisa permitir o recurso de locks.
Você agora pode configurar cada uma das suas entidades para usar o melhor modo de cache, como no trecho abaixo:
<?php
namespace DoctrineNaPratica\Model;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @ORM\Entity
* @ORM\Table(name="User")
* @ORM\Cache(usage="NONSTRICT_READ_WRITE")
*/
class User
{
Neste exemplo foi escolhido o modo NONSTRICT_READ_WRITE e o cache vai permitir que as entidades sejam alteradas normalmente. Quando uma alteração é realizada a entidade é persistida do banco de dados e também alterada automaticamente no cache, de forma que as próximas requisições possam acessá-la sem a realização de uma nova consulta no banco de dados.
Na imagem abaixo é possível ver o cache funcionando no painel do Z-Ray
Na documentação do Doctrine é possível ver outras funcionalidades como adicionar um log, alterar o tempo de vida do cache ou mesmo realizar a limpeza do mesmo.
Realmente uma funcionalidade que permite aumentar muito a performance de projetos usando este excelente ORM.
P.S.: este post é uma continuação do capítulo sobre performance do livro Doctrine na prática que pode ser adquirido no Leanpub