卓越飞翔博客卓越飞翔博客

卓越飞翔 - 您值得收藏的技术分享站
技术文章34397本站已运行393

为什么我的redis缓存只返回部分数据

为什么我的redis缓存只返回部分数据

php小编香蕉在使用redis缓存时,可能会遇到一个常见问题:为什么我的redis缓存只返回部分数据?这个问题可能有多种原因,包括缓存设置不当、缓存键名冲突、缓存过期等。在解决这个问题之前,我们需要仔细检查代码和配置,确保缓存的正常运行。本文将为您分析可能的原因,并提供解决方案,帮助您解决这个问题,确保redis缓存返回完整的数据。

问题内容

该函数检查 postgres 与 redis 缓存的实现情况 当我发出 get 请求时,第一个结果返回所有数据,但是当我发出下一个结果时,数据的某些字段丢失

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

}

这是我的用户结构:type user struct { id uuid.uuid json:"id" 名字字符串 json:"first_name" 姓氏字符串 json:"last_name" 其他名称字符串 json:"other_name" 用户名字符串 json:"user_name" 密码字符串 json:"密码" 电子邮件字符串 json:"email" 配置文件图像字符串 json:"profile_image" 状态字符串 json:"status" isadmin bool json:"is_admin" 角色字符串 json:"角色" 性别字符串 json:"性别" 电话号码字符串 json:"phone_number" createdat time.时间 json:"created_at" updatedat time.时间 json:"updated_at" }

解决方法

我整理了一个小例子来尝试帮助您。作为前提,我简化了您的示例,只是为了提供此处重要的内容。由于程序的某些部分尚未共享,我不得不做一些猜测。如果这个例子没有用,请让我知道缺少什么,我会更新我的答案。让我们从我使用 docker 在本地运行 postgres/redis 的命令开始。

设置

我使用的命令是:

  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

现在,让我们切换到代码。

程序

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)
    }
}

让我们仔细看看每个部分(按编号评论划分):

  1. 在客户端初始化中没有太多可说的。我们初始化了指向本地实例的客户端
  2. 然后,我们使用一些虚拟数据设置数据库
  3. 我们尝试从 redis 实例获取数据。如果找到它们,我们将其打印出来并终止程序
  4. 如果在缓存中没有找到数据,那么我们从数据库中获取它们
  5. 最后,如果我们从数据库中获取数据,则可以安全地假设我们也应该将它们放入缓存中

在这两种情况下,我们都使用相同的字段获取相同数量的数据。因此,如果您坚持这个示例并将其调整为您的模型和项目类型(我的不是网络项目),您应该会很好。如果您仍然遇到问题,请告诉我。谢谢!

卓越飞翔博客
上一篇: 如何将带有 $ 和 , 的货币列转换为数字
下一篇: 返回列表
留言与评论(共有 0 条评论)
   
验证码:
隐藏边栏