Mettre en cache les résultats d'exécution des requêtes

GolangBeginner
Pratiquer maintenant

Introduction

Dans ce projet, vous allez apprendre à implémenter une bibliothèque de mise en cache qui prend en compte le temps d'expiration en utilisant le package singleflight en Go. Cette bibliothèque de mise en cache peut être utilisée dans des systèmes distribués pour mettre en cache les résultats d'exécution des requêtes, améliorant ainsi les performances de votre application.

👀 Aperçu

$ /usr/local/go/bin/go test --race
PASS
ok      cacheflight     1.263s

🎯 Tâches

Dans ce projet, vous allez apprendre :

  • Comment initialiser un module Go et installer les packages requis
  • Comment implémenter la bibliothèque de mise en cache en utilisant le package singleflight
  • Comment tester la bibliothèque de mise en cache pour vous assurer qu'elle fonctionne comme prévu

🏆 Réalisations

Après avoir terminé ce projet, vous serez capable de :

  • Comprendre les concepts de base de la mise en cache et du package singleflight en Go
  • Implémenter une bibliothèque de mise en cache qui prend en compte le temps d'expiration
  • Intégrer la bibliothèque de mise en cache dans votre système distribué pour améliorer les performances de votre application

Initialiser le module et installer les packages requis

Dans cette étape, vous allez apprendre à initialiser le module et à installer les packages requis pour le projet.

  1. Ouvrez un terminal dans le répertoire /home/labex/project.

  2. Initialisez le module à l'aide de la commande suivante :

    /usr/local/go/bin/go mod init cacheflight
    
  3. Installez les packages requis à l'aide des commandes suivantes :

    /usr/local/go/bin/go get github.com/golang/groupcache/singleflight
    /usr/local/go/bin/go get github.com/stretchr/testify/assert
    

Implémenter la bibliothèque de mise en cache

Dans cette étape, vous allez implémenter la bibliothèque de mise en cache basée sur le package singleflight.

  1. Ouvrez le fichier cacheflight.go dans le répertoire /home/labex/project.

  2. Ajoutez le contenu nécessaire à import.

    import (
        "sync"
        "time"
    
        "github.com/golang/groupcache/singleflight"
    )
    
  3. Ajoutez le contenu nécessaire à type Group et type cacheResult.

    // cacheResult est le résultat du cache
    type cacheResult struct {
        data      interface{} // les données du cache
        ctime     time.Time   // temps de création du cache
        isRunning chan bool   // est-ce que la fonction est en cours d'exécution
    }
    
    // Group est la structure principale
    type Group struct {
        cacheExpiration time.Duration          // expiration du cache
        sfg             *singleflight.Group    // groupe singleflight
        cache           map[string]cacheResult // résultat du cache
        mu              sync.Mutex             // verrou
    }
    
  4. Implémentez la fonction NewGroup pour retourner un nouveau groupe de mise en cache avec le temps d'expiration du cache spécifié.

    func NewGroup(cacheExpiration time.Duration) (group *Group) {
        group = &Group{
            sfg:             &singleflight.Group{},
            cache:           make(map[string]cacheResult),
            cacheExpiration: cacheExpiration,
        }
        return
    }
    
  5. Implémentez la fonction do pour gérer la logique de mise en cache.

    func (g *Group) do(key string, fn func() (interface{}, error)) (ret interface{}, err error) {
        return g.sfg.Do(key, func() (interface{}, error) {
            g.mu.Lock()
            result, ok := g.cache[key]
            if result.isRunning!= nil {
                g.mu.Unlock()
                // attendre que fn soit terminé
                <-result.isRunning
                return g.do(key, fn)
            } else if!ok || result.ctime.Add(g.cacheExpiration).Before(time.Now()) {
                // si le cache n'existe pas ou est expiré
                var run = make(chan bool)
                result.isRunning = run
                g.cache[key] = result
                // lorsque fn est terminé et que le canal run est fermé, laisser les autres goroutines obtenir le cache
                defer close(run)
            } else {
                // si le cache existe et n'est pas expiré
                g.mu.Unlock()
                return result.data, nil
            }
    
            g.mu.Unlock()
    
            // différentes clés peuvent s'exécuter en même temps
            ret, err = fn()
            if err!= nil {
                return ret, nil
            }
    
            result = cacheResult{
                data:  ret,
                ctime: time.Now(),
            }
            g.mu.Lock()
            g.cache[key] = result
            g.mu.Unlock()
    
            return ret, nil
        })
    }
    
  6. Implémentez la fonction Do pour être un wrapper autour de la fonction do.

    func (g *Group) Do(key string, fn func() (interface{}, error)) (ret interface{}, err error) {
        return g.do(key, fn)
    }
    

Tester la bibliothèque de mise en cache

Dans cette étape, vous allez tester la bibliothèque de mise en cache pour vous assurer qu'elle fonctionne comme prévu.

  1. Ouvrez un terminal dans le répertoire /home/labex/project.

  2. Exécutez la commande suivante pour exécuter les tests :

    cd /home/labex/project
    /usr/local/go/bin/go test --race
    
  3. Si la fonction de mise en cache a été correctement implémentée, vous verrez la sortie suivante :

    PASS
    ok      cacheflight     1.263s
    
  4. Si vous rencontrez une erreur de temps d'attente, exécutez les commandes suivantes dans le terminal puis cliquez sur le bouton de reinspection pour passer le contrôle :

    cd /home/labex/project
    /usr/local/go/bin/go test --race
    

Félicitations! Vous avez réussi à implémenter la bibliothèque de mise en cache basée sur le package singleflight. Vous pouvez désormais utiliser cette bibliothèque dans votre système distribué pour mettre en cache les résultats d'exécution des requêtes et améliorer les performances de votre application.

Résumé

Félicitations! Vous avez terminé ce projet. Vous pouvez pratiquer plus de laboratoires dans LabEx pour améliorer vos compétences.

✨ Vérifier la solution et pratiquer✨ Vérifier la solution et pratiquer✨ Vérifier la solution et pratiquer