首頁  >  文章  >  後端開發  >  為什麼我的redis快取只回傳部分數據

為什麼我的redis快取只回傳部分數據

王林
王林轉載
2024-02-08 21:33:211001瀏覽

為什麼我的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. 最後,如果我們從資料庫中獲取數據,則可以安全地假設我們也應該將它們放入快取中

在這兩種情況下,我們都使用相同的欄位來取得相同數量的資料。因此,如果您堅持這個範例並將其調整為您的模型和項目類型(我的不是網頁項目),您應該會很好。如果您仍然遇到問題,請告訴我。謝謝!

以上是為什麼我的redis快取只回傳部分數據的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:stackoverflow.com。如有侵權,請聯絡admin@php.cn刪除