Maison  >  Article  >  développement back-end  >  Pourquoi mon cache Redis ne renvoie-t-il que des données partielles

Pourquoi mon cache Redis ne renvoie-t-il que des données partielles

王林
王林avant
2024-02-08 21:33:211001parcourir

Pourquoi mon cache Redis ne renvoie-t-il que des données partielles

Lors de l'utilisation du cache Redis, vous pouvez rencontrer un problème courant : Pourquoi mon cache Redis ne renvoie-t-il qu'une partie des données ? Ce problème peut avoir plusieurs causes, notamment des paramètres de cache incorrects, des conflits de noms de clé de cache, l'expiration du cache, etc. Avant de résoudre ce problème, nous devons vérifier soigneusement le code et la configuration pour nous assurer que le cache fonctionne correctement. Cet article analysera pour vous les causes possibles et fournira des solutions pour vous aider à résoudre ce problème et garantir que le cache Redis renvoie des données complètes.

Contenu de la question

Cette fonction vérifie l'implémentation du cache postgres et redis Lorsque je fais une requête get, le premier résultat renvoie toutes les données, mais lorsque je fais le résultat suivant, certains champs de données manquent

func (usr *UserImplementation) GetAllUsers(ctx context.Context) ([]models.User, error) {

    cachedUsers, err := databaseapi.Redis_CacheDB_Api()
    if err != nil {
        return nil, fmt.Errorf("error connecting to Redis cache: %v", err)
    }

    // pipe := cachedUsers.TxPipeline()

    cachedData, err := cachedUsers.Get(ctx, "users").Result()
    if err != nil && err != redis.Nil {
        return nil, fmt.Errorf("error retrieving cached data: %v", err)
    }

    if cachedData != "" {
        // Data found in the cache, return the cached data
        var cachedUsers []models.User
        err := json.Unmarshal([]byte(cachedData), &cachedUsers)
        if err != nil {
            return nil, fmt.Errorf("error unmarshaling cached data: %v", err)
        }
        return cachedUsers, nil
    }

    users, err := usr.pg.Postgres_DB_Api().DB.GetAllUsers(ctx)
    if err != nil {
        return nil, fmt.Errorf("error: %v", err.Error())
    }

    cacheData, err := json.Marshal(users)
    if err != nil {
        return nil, fmt.Errorf("error marshaling data for caching: %v", err)
    }

    expiration := time.Hour

    err = cachedUsers.Set(ctx, "users", string(cacheData), expiration).Err()
    if err != nil {
        return nil, fmt.Errorf("error caching data: %v", err)
    }

    return models.DatabaseUsersToUsers(users), nil

}

Voici ma structure utilisateur : tapez user struct { identifiant uuid.uuid json:"id" Chaîne de nom json:"first_name" Chaîne de nom de famille json:"last_name" Autres chaînes de noms json:"other_name" Chaîne de nom d'utilisateur json:"user_name" Chaîne de mot de passe json:"密码" Chaîne d'e-mail json:"email" Chaîne d'image de profil json:"profile_image" chaîne de statut json:"status" isadmin booléen json:"is_admin" chaîne de rôle json:"角色" Chaîne de genre json:"性别" Chaîne de numéro de téléphone json:"phone_number" créé à l'heure json:"created_at" mis à jour à l'heure json:"updated_at" }

Solution de contournement

J'ai rassemblé un petit exemple pour essayer de vous aider. En principe, j'ai simplifié votre exemple juste pour fournir ce qui est important ici. Étant donné que certaines parties du programme n'ont pas encore été partagées, je dois faire quelques suppositions. Si cet exemple ne fonctionne pas, faites-moi savoir ce qui manque et je mettrai à jour ma réponse. Commençons par ma commande pour exécuter postgres/redis localement à l'aide de Docker.

Paramètres

La commande que j'ai utilisée est :

  1. docker run -d -p 54322:5432 -e postgres_password=postgres postgres
  2. docker run -d --name redis-stack -p 6379:6379 -p 8001:8001 redis/redis-stack:latest

Maintenant, passons au code.

Programme

package main

import (
    "context"
    "encoding/json"
    "fmt"
    "time"

    "github.com/redis/go-redis/v9"
    "gorm.io/driver/postgres"
    "gorm.io/gorm"
)

type user struct {
    ID        int    `json:"id"`
    FirstName string `json:"first_name"`
    LastName  string `json:"last_name"`
}

func main() {
    // 1. instantiate clients
    dsn := "host=localhost port=54322 user=postgres password=postgres"
    db, err := gorm.Open(postgres.Open(dsn))
    if err != nil {
        panic(err)
    }
    redisClient := redis.NewClient(&redis.Options{
        Addr:     ":6379",
        Password: "",
        DB:       0,
    })

    // 2. automigrate objects & seed dummy data
    db.AutoMigrate(&user{})
    db.Create(&user{ID: 1, FirstName: "John", LastName: "Doe"})
    db.Create(&user{ID: 2, FirstName: "Suzy", LastName: "White"})

    // 3. attempt to retrieve from cache
    var users []user
    cachedUsers, err := redisClient.Get(context.Background(), "users").Result()
    if err != nil && err != redis.Nil {
        panic(fmt.Errorf("err retrieving cached data: %v", err))
    }
    if cachedUsers != "" {
        if err := json.Unmarshal([]byte(cachedUsers), &users); err != nil {
            panic(fmt.Errorf("err while unmarshaling data: %v", err))
        }
        fmt.Println("users taken from Redis")
        for _, v := range users {
            fmt.Println(v)
        }
        return
    }

    // 4. retrieve from the DB
    if err := db.Model(&user{}).Find(&users).Error; err != nil {
        panic(fmt.Errorf("err while retrieving from DB: %v", err))
    }

    // 5. set the key within the cache
    rawUsers, err := json.Marshal(users)
    if err != nil {
        panic(fmt.Errorf("err while marshaling users: %v", err))
    }
    if err := redisClient.Set(context.Background(), "users", rawUsers, time.Minute*15).Err(); err != nil {
        panic(fmt.Errorf("err while setting key in cache: %v", err))
    }
    fmt.Println("users taken from DB")
    for _, v := range users {
        fmt.Println(v)
    }
}

Regardons de plus près chaque section (divisée par des commentaires numérotés) :

  1. Pas grand chose à dire sur l'initialisation du client. Nous avons initialisé le client pointant vers l'instance locale
  2. Ensuite, nous configurons la base de données avec des données factices
  3. Nous essayons d'obtenir des données de l'instance Redis. S'ils sont trouvés, nous les imprimons et terminons le programme
  4. Si les données ne sont pas trouvées dans le cache, alors nous les récupérons de la base de données
  5. Enfin, si nous obtenons des données de la base de données, il est raisonnable de supposer que nous devrions également les mettre dans le cache

Dans les deux cas, nous utilisons les mêmes champs pour obtenir la même quantité de données. Donc, si vous vous en tenez à cet exemple et l'adaptez à votre modèle et à votre type de projet (le mien n'était pas un projet Web), tout devrait bien se passer. Si vous rencontrez toujours des problèmes, faites-le-moi savoir. Merci!

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer