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

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

王林
發布: 2024-02-08 21:33:21
轉載
1149 人瀏覽過

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

php小編香蕉在使用redis快取時,可能會遇到一個常見問題:為什麼我的redis快取只回傳部分資料?這個問題可能有多種原因,包括快取設定不當、快取鍵名衝突、快取過期等。在解決這個問題之前,我們需要仔細檢查程式碼和配置,確保快取的正常運作。本文將為您分析可能的原因,並提供解決方案,幫助您解決這個問題,確保redis快取返回完整的資料。

問題內容

此函數檢查 postgres 與 redis 快取的實作情況 當我發出 get 請求時,第一個結果會傳回所有數據,但是當我發出下一個結果時,資料的某些欄位遺失

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

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

#現在,讓我們切換到程式碼。

程式

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

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中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板