Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Desmistificando caching no Doctrine ORM

Luís Cobucci
September 12, 2020

Desmistificando caching no Doctrine ORM

Nossos softwares devem ser rápidos independentemente de qualquer camada de cache. Porém, de vez em quando é necessário fazer caching para otimizar o sistema e prover respostas mais rápidas.

Essa palestra aborda os diferentes níveis de caching oferecidos pelo Doctrine ORM (metadata, query, result set, and second level cache), como eles funcionam em conjunto com a biblioteca e como modelar nossas entidades para tirar o maior proveito deles.

Luís Cobucci

September 12, 2020
Tweet

More Decks by Luís Cobucci

Other Decks in Programming

Transcript

  1. Template Campaign Message Customer 1 * * * 1 1

    Ordem de inserção é Ordem de inserção é importante! importante!
  2. Template Campaign Message Customer 1 * * * 1 1

    Ordem de inserção é Ordem de inserção é importante! importante! INSERT INTO customer (name, email) VALUES (“Luís Cobucci”, “[email protected]”); SET @customer_id = LAST_INSERT_ID();
  3. Template Campaign Message Customer 1 * * * 1 1

    Ordem de inserção é Ordem de inserção é importante! importante! INSERT INTO customer (name, email) VALUES (“Luís Cobucci”, “[email protected]”); SET @customer_id = LAST_INSERT_ID(); INSERT INTO template (name, body) VALUES (“Template 1”, “blah… blah… blah…”);
  4. Template Campaign Message Customer 1 * * * 1 1

    Ordem de inserção é Ordem de inserção é importante! importante! INSERT INTO customer (name, email) VALUES (“Luís Cobucci”, “[email protected]”); SET @customer_id = LAST_INSERT_ID(); INSERT INTO campaign (title, template_id, message) VALUES (“Test”, LAST_INSERT_ID(), “blah… blah… blah…”); INSERT INTO template (name, body) VALUES (“Template 1”, “blah… blah… blah…”);
  5. Template Campaign Message Customer 1 * * * 1 1

    Ordem de inserção é Ordem de inserção é importante! importante! INSERT INTO customer (name, email) VALUES (“Luís Cobucci”, “[email protected]”); SET @customer_id = LAST_INSERT_ID(); INSERT INTO campaign (title, template_id, message) VALUES (“Test”, LAST_INSERT_ID(), “blah… blah… blah…”); INSERT INTO message (campaign_id, customer_id, sent) VALUES (LAST_INSERT_ID(), @customer_id, FALSE); INSERT INTO template (name, body) VALUES (“Template 1”, “blah… blah… blah…”);
  6. Template Campaign Message Customer 1 * * * 1 1

    Ordem de inserção é Ordem de inserção é importante! importante! INSERT INTO customer (name, email) VALUES (“Luís Cobucci”, “[email protected]”); SET @customer_id = LAST_INSERT_ID(); INSERT INTO campaign (title, template_id, message) VALUES (“Test”, LAST_INSERT_ID(), “blah… blah… blah…”); INSERT INTO message (campaign_id, customer_id, sent) VALUES (LAST_INSERT_ID(), @customer_id, FALSE); INSERT INTO template (name, body) VALUES (“Template 1”, “blah… blah… blah…”); Não esqueça de usar transações!
  7. declare(strict_types=1); $customer = new Customer('Luís Cobucci', '[email protected]'); $template = new

    Template('Template 1', 'blah… blah… blah…'); $campaign = new Campaign($template, 'Test', 'blah… blah… blah…'); $message = new Message($campaign, $customer);
  8. declare(strict_types=1); $customer = new Customer('Luís Cobucci', '[email protected]'); $template = new

    Template('Template 1', 'blah… blah… blah…'); $campaign = new Campaign($template, 'Test', 'blah… blah… blah…'); $message = new Message($campaign, $customer); $entityManager->persist($customer); $entityManager->persist($template); $entityManager->persist($campaign); $entityManager->persist($message);
  9. declare(strict_types=1); $customer = new Customer('Luís Cobucci', '[email protected]'); $template = new

    Template('Template 1', 'blah… blah… blah…'); $campaign = new Campaign($template, 'Test', 'blah… blah… blah…'); $message = new Message($campaign, $customer); $entityManager->persist($customer); $entityManager->persist($template); $entityManager->persist($campaign); $entityManager->persist($message); $entityManager->flush();
  10. declare(strict_types=1); $customer = new Customer('Luís Cobucci', '[email protected]'); $template = new

    Template('Template 1', 'blah… blah… blah…'); $campaign = new Campaign($template, 'Test', 'blah… blah… blah…'); $message = new Message($campaign, $customer); $entityManager->persist($customer); $entityManager->persist($template); $entityManager->persist($campaign); $entityManager->persist($message); $entityManager->flush(); // transação implicita aqui
  11. /** @ORM\Entity */ class Customer { /** * @ORM\Id *

    @ORM\GeneratedValue * @ORM\Column(type="integer") */ private int $id; /** @ORM\Column(type="string") */ private string $name; /** @ORM\Column(type="string") */ private string $email; }
  12. /** @ORM\Entity */ class Customer { /** * @ORM\Id *

    @ORM\GeneratedValue * @ORM\Column(type="integer") */ private int $id; /** @ORM\Column(type="string") */ private string $name; /** @ORM\Column(type="string") */ private string $email; }
  13.          

         
  14.          

             
  15.          

               
  16.          

               
  17.          

                
  18.          

                 ? ?
  19. “ a hardware or software component that stores data so

    future requests for that data can be served faster; the data stored in a cache might be the result of an earlier computation, or the duplicate of data stored elsewhere. Cache (computing) - Wikipedia
  20. “ a hardware or software component that stores data so

    future requests for that data can be served faster; the data stored in a cache might be the result of an earlier computation, or the duplicate of data stored elsewhere. Cache (computing) - Wikipedia
  21. Nossa App Cache API Externa 2. oh nao, cache miss!

    1. Me da “externa.resultado”
  22. Nossa App Cache API Externa 2. oh nao, cache miss!

    1. Me da “externa.resultado” 3. Me da os dados!
  23. Nossa App Cache API Externa 2. oh nao, cache miss!

    1. Me da “externa.resultado” 3. Me da os dados! 4. Aqui estao!
  24. Nossa App Cache API Externa 2. oh nao, cache miss!

    1. Me da “externa.resultado” 3. Me da os dados! 4. Aqui estao! 5. Armazene “externa.resultado”
  25. Nossa App Cache API Externa 2. oh nao, cache miss!

    1. Me da “externa.resultado” 3. Me da os dados! 4. Aqui estao! 5. Armazene “externa.resultado” 6. Armazenado!
  26. Nossa App Cache API Externa 2. oh yeah, cache hit!

    1. Me da “externa.resultado”
  27. Nossa App Cache API Externa 2. oh yeah, cache hit!

    1. Me da “externa.resultado” Quando o cache deve ser invalidado?
  28. “ There are two hard things in Computer Science: cache

    invalidation, naming things, and off-by-one errors. Senso comum
  29. “ There are two hard things in Computer Science: cache

    invalidation, naming things, and off-by-one errors. Senso comum
  30. /** @ORM\Entity */ class Customer { /** * @ORM\Id *

    @ORM\GeneratedValue * @ORM\Column(type="integer") */ private int $id; /** @ORM\Column(type="string") */ private string $name; /** @ORM\Column(type="string") */ private string $email; }
  31. /** @ORM\Entity */ class Customer { /** * @ORM\Id *

    @ORM\GeneratedValue * @ORM\Column(type="integer") */ private int $id; /** @ORM\Column(type="string") */ private string $name; /** @ORM\Column(type="string") */ private string $email; } Metadados
  32. SELECT customer FROM Customer customer; SELECT c0.id AS id_0, c0.name

    AS name_1, c0.email AS email_2 FROM customer c0;
  33. declare(strict_types=1); $query = 'SELECT COUNT(m) FROM Message m WHERE m.user

    = :user'; $count = $entityManager->createQuery($query) ->setParameter('user', 1) ->getSingleScalarResult();
  34. declare(strict_types=1); $query = 'SELECT COUNT(m) FROM Message m WHERE m.user

    = :user'; $count = $entityManager->createQuery($query) ->setParameter('user', 1) ->useResultCache(true, 3600) ->getSingleScalarResult();
  35. declare(strict_types=1); $query = 'SELECT COUNT(m) FROM Message m WHERE m.user

    = :user'; $count = $entityManager->createQuery($query) ->setParameter('user', 1) ->useResultCache(true, 3600) ->getSingleScalarResult(); Olha a invalidação manual aí!
  36. declare(strict_types=1); use Doctrine\Common\Cache\RedisCache; use Doctrine\ORM\Cache as L2C; use Doctrine\ORM\Configuration; $level2Cache

    = new RedisCache(); $level2Config = new L2C\CacheConfiguration(); $level2Config->setSecondLevelCacheEnabled( new L2C\DefaultCacheFactory( new L2C\RegionsConfiguration(), $level2Cache ) ); $configuration = new Configuration(); // … $configuration->setSecondLevelCacheEnabled(true); $configuration->setSecondLevelCacheConfiguration($level2Config);
  37. /** * @ORM\Entity * @ORM\Cache(usage=”NONSTRICT_READ_WRITE”) */ class Message { //

    ... /** * @ORM\ManyToOne(targetEntity=Customer::class) * @ORM\Cache(usage=”READ_ONLY”) */ private Customer $customer; // ... }
  38. declare(strict_types=1); $query = 'SELECT m FROM Message m WHERE m.user

    = :user'; $count = $entityManager->createQuery($query) ->setParameter('user', 1) ->setCacheable(true) ->getResult();