Maxence POUTORD

RevealJS Tips

Redis c'est quoi ?

  • REmote DIctionary Server
  • SGBD Clé-valeur
  • Mouvance NoSQL (Not only SQL)
  • Très scalable
  • ...et surtout très rapide ! (Stockage en RAM)

Qui l'utilise ?

  • Stack Overflow
  • You**** (ce n'est pas YouTube)
  • Github
  • Twitter
  • ...

[EN] TechStacks using Redis

Utilisations

  • Base NoSQL
  • Cache
  • Message broker
  • ...

Getting started

Requêtes de base (1/2)


127.0.0.1:6379> SET ping pong
OK
      
127.0.0.1:6379> GET ping
"pong"
      
127.0.0.1:6379> GET foo
(nil)
      
127.0.0.1:6379> SET user:1 "Maxence POUTORD"
OK
127.0.0.1:6379> SET user:2 "Lara CROFT"
OK
      
127.0.0.1:6379> KEYS *
1) "user:2"
2) "user:1"
3) "ping"
      
127.0.0.1:6379> KEYS user*
1) "user:2"
3) "user:1"
      

Requêtes de base (2/2)


127.0.0.1:6379> DEL ping user:1
(integer) 2
      
127.0.0.1:6379> KEYS *
1) "user:2"
      
127.0.0.1:6379> FLUSHDB
OK
      
127.0.0.1:6379> KEYS *
(empty list or set)
      

Time to Live


127.0.0.1:6379> SETEX 5 ethan "votre mission si vous l'acceptez..."
OK
      
127.0.0.1:6379> TTL ethan
5
      
127.0.0.1:6379> GET ethan
"votre mission si vous l'acceptez..."
      
# 5' later
127.0.0.1:6379> GET ethan
(nil)
      

Redis et PHP/SF2

PHP : predis


$client = new Predis\Client();
$client->set('foo', 'bar');
$value = $client->get('foo'); //bar
      

https://github.com/nrk/predis

SF : SncRedisBundle

  • Doctrine caching
  • Monolog logging
  • SwiftMailer spooling

$redis_cluster = $this->container->get('snc_redis.cluster');
$val = $redis_cluster->get('ab:cd');
$val = $redis_cluster->get('ef:gh');
$val = $redis_cluster->get('ij:kl');
      

https://github.com/snc/SncRedisBundle

Redis et Doctrine

RTFM

Documentation doctrine

Système de cache

  • Query cache : transformation DQL -> SQL
  • Result cache : résultat de la requête
  • Metadata cache : annotation des entities

Query cache + Metadata cache

  • Implicite !
    (à configurer dans le config.yml)

Result cache


public function findCurrent()
{
    $qb = $this->createQueryBuilder('m');

    $qb
        ->select('m')
        ->where('m.id = 1')
        ->leftJoin('m.media', 'me')
        ->addSelect('me');

    return $qb
        ->getQuery()
        ->useResultCache(true, 3600, 'magazine_current')
        ->getSingleResult()
    ;
}
      

Invalidation du cache

"There are only two hard things in Computer Science:
cache invalidation and naming things"
Phil Karlton

Evenements Doctrine

Annotations de l'entité


use Doctrine\ORM\Mapping as ORM;

/**
 * Magazine
 *
 * @ORM\Table(name="magazine_accueil")
 * @ORM\Entity(repositoryClass="LP\ConfigBundle\Repository\MagazineRepository")
 * @ORM\EntityListeners({"LP\ConfigBundle\Service\MagazineListener"})
 */
class Magazine implements MagazineInterface
{
    //...
}
      

Événements de cycle de vie

prePertist
postPertist
Avant/Après création
preUpdate
postUpdate
Avant/Après modification
preRemove
postRemove
Avant/Après suppression
postLoad Après chargement

Liste des événements de cycle de vie des entités

Le service


use Doctrine\ORM\Event\LifecycleEventArgs;
use LP\ConfigBundle\Entity\Magazine;

class MagazineListener
{
    private $cacheDriver;

    public function __construct($cacheDriver)
    {
        $this->cacheDriver = $cacheDriver;
    }

    public function postPersist(Magazine $magazine, LifecycleEventArgs $args)
    {
        $this->cacheDriver->expire('[magazine_current][1]', 0);
    }

    public function postUpdate(Magazine $magazine, LifecycleEventArgs $args)
    {
        $this->cacheDriver->expire('[magazine_current][1]', 0);
    }

    //don't need PostRemove() method
}
      

Définition du service


# app/config/services.yml
magazine_listener:
    class: LP\ConfigBundle\Service\MagazineListener
    arguments:
        - "@snc_redis.doctrine"
    tags:
        - { name: doctrine.orm.entity_listener }
      

Aller plus loin