Maison >développement back-end >Golang >La pratique consistant à utiliser le cache pour accélérer l'efficacité de l'accès à la base de données dans Golang.

La pratique consistant à utiliser le cache pour accélérer l'efficacité de l'accès à la base de données dans Golang.

WBOY
WBOYoriginal
2023-06-20 10:12:101577parcourir

La pratique consistant à utiliser le cache pour accélérer l'efficacité de l'accès à la base de données dans Golang

À mesure que les applications Web deviennent de plus en plus complexes, l'accès à la base de données devient de plus en plus fréquent. L’accès à la base de données est généralement une opération très chronophage, surtout lorsque la quantité de données est importante. Afin d'améliorer l'efficacité de l'accès aux bases de données, des stratégies telles que la mise en cache peuvent être utilisées pour optimiser l'accès aux bases de données.

Cet article présentera la pratique de l'utilisation du cache pour accélérer l'accès aux bases de données dans Golang. Nous utiliserons Golang comme langage de développement, Redis comme serveur de cache et MySQL comme serveur de base de données pour les expériences.

1. Configurer l'environnement

Avant de commencer, nous devons configurer l'environnement. Installez d'abord les serveurs Golang et MySQL et Redis, qui ne seront pas décrits ici.

Ensuite, installez le pilote Go pour Redis et MySQL locaux dans Golang :

go get github.com/go-redis/redis/v8
go get github.com/go-sql-driver/mysql

2. Écrivez le code

Ensuite, nous écrivons le code pour implémenter la mise en cache afin d'accélérer l'accès à la base de données.

Le premier est le code d'accès à la base de données. Nous avons défini une variable globale appelée DB pour la connexion à MySQL. Ensuite, nous avons défini une fonction getUserByID pour interroger les informations d'un utilisateur depuis MySQL :

package main
 
import (
   "database/sql"
   "fmt"
   "log"
 
   _ "github.com/go-sql-driver/mysql"
)
 
var DB *sql.DB
 
type User struct {
   ID       int
   Username string
   Password string
   Age      int
}
 
func init() {
   db, err := sql.Open("mysql", "root:password@tcp(127.0.0.1:3306)/test?charset=utf8")
   if err != nil {
      log.Fatal("Open mysql failed,err:", err)
      return
   }
   DB = db
   fmt.Println("Connect to mysql success")
}
 
func getUserByID(id int) (*User, error) {
   var user User
   query := "SELECT id, username, password, age FROM users WHERE id=?"
   err := DB.QueryRow(query, id).Scan(&user.ID, &user.Username, &user.Password, &user.Age)
   if err != nil {
      log.Println(err)
      return nil, err
   }
   return &user, nil
}

Ensuite, nous avons ajouté une logique de mise en cache à cette fonction getUserByID. Plus précisément, nous essayons d'abord de lire les informations utilisateur demandées à partir du cache Redis via la fonction getUserByID. S'il n'y a aucun enregistrement d'informations pour l'utilisateur dans Redis, les informations utilisateur sont lues à partir de MySQL et stockées dans Redis pour le prochain accès. Si les informations utilisateur sont enregistrées dans Redis, les informations utilisateur sont renvoyées directement depuis Redis :

package main
 
import (
   "database/sql"
   "encoding/json"
   "fmt"
   "log"
   "strconv"
 
   "github.com/go-redis/redis/v8"
   _ "github.com/go-sql-driver/mysql"
)
 
var DB *sql.DB
var RedisClient *redis.Client
 
type User struct {
   ID       int
   Username string
   Password string
   Age      int
}
 
func init() {
   db, err := sql.Open("mysql", "root:password@tcp(127.0.0.1:3306)/test?charset=utf8")
   if err != nil {
      log.Fatal("Open mysql failed,err:", err)
      return
   }
   DB = db
   fmt.Println("Connect to mysql success")
 
   RedisClient = redis.NewClient(&redis.Options{
      Addr: "127.0.0.1:6379",
   })
   pong, err := RedisClient.Ping(RedisClient.Context()).Result()
   if err != nil {
      panic(err)
      return
   }
   fmt.Println("Connect to redis success: ", pong)
}
 
func getUserByID(id int) (*User, error) {
   var user User
   key := "user-" + strconv.Itoa(id)
 
   // 1.尝试从Redis中读取用户信息
   val, err := RedisClient.Get(RedisClient.Context(), key).Result()
   if err == redis.Nil {
      fmt.Println("Cache miss")
   } else if err != nil {
      log.Println("Get from Redis fail:", err)
   } else {
      fmt.Println("Get from Redis:", val)
      if err := json.Unmarshal([]byte(val), &user); err != nil { // 将json字符串转换为结构体
         log.Panicln("Unmarshal to user fail:", err)
      }
      return &user, nil
   }
 
   // 2.如果Redis中没有,从MySQL中查询
   query := "SELECT id, username, password, age FROM users WHERE id=?"
   err = DB.QueryRow(query, id).Scan(&user.ID, &user.Username, &user.Password, &user.Age)
   if err != nil {
      log.Println(err)
      return nil, err
   }
 
   // 3.然后更新Redis缓存
   val, err = json.Marshal(user) // 将结构体转换为json字符串
   if err != nil {
      log.Panicln("Marshal user fail:", err)
   }
   err = RedisClient.Set(RedisClient.Context(), key, val, 0).Err()
   if err != nil {
      log.Panicln("Cache to Redis fail:", err)
   }
   return &user, nil
}

3 Test

Nous avons terminé l'écriture de la logique du cache. Testons maintenant ce code et voyons comment il fonctionne.

Tout d'abord, notre programme de test doit lire les informations utilisateur de MySQL pour la première fois :

func main() {
   id := 1
   user, err := getUserByID(id)
   if err != nil {
      log.Fatal(err)
      return
   }
   fmt.Printf("User info: id=%d, username=%s, password=%s, age=%d
",
      user.ID, user.Username, user.Password, user.Age)
}

Exécutez le programme, le résultat est le suivant :

Cache miss
User info: id=1, username=kirito, password=123456, age=18

Vous pouvez voir que le programme extrait les informations utilisateur de MySQL et le stocke dans le cache Redis.

Après avoir interrogé le même utilisateur pour la deuxième fois, le programme lira les informations utilisateur de Redis au lieu d'accéder à la base de données MySQL :

func main() {
   id := 1
   user, err := getUserByID(id)
   if err != nil {
      log.Fatal(err)
      return
   }
   fmt.Printf("User info: id=%d, username=%s, password=%s, age=%d
",
      user.ID, user.Username, user.Password, user.Age)
}

Exécutez le programme et le résultat est le suivant :

Get from Redis: {"ID":1,"Username":"kirito","Password":"123456","Age":18}
User info: id=1, username=kirito, password=123456, age=18

Vous pouvez voir que le programme lit l'utilisateur directement à partir des informations Redis sans accéder à la base de données MySQL, ce qui prouve l'utilité de la mise en cache.

Résumé

Dans cet article, nous avons présenté la pratique consistant à utiliser le mécanisme de mise en cache Redis dans Golang pour optimiser l'efficacité de l'accès à la base de données. En écrivant la fonction getUserByID, lors de l'interrogation des informations utilisateur, nous essayons d'abord de lire les informations de Redis pour accélérer la requête. Si les informations utilisateur n'existent pas dans Redis, nous les lisons depuis MySQL et les stockons dans Redis. Une fois les données mises en cache, lorsque le programme accède plusieurs fois aux mêmes données, il peut lire directement à partir du cache sans accéder à la base de données à chaque fois.

Il est à noter que l'utilisation du cache doit éviter la génération de données sales. Pour les opérations CRUD sur les données, le cache doit également suivre les opérations sur les données pour garantir la cohérence des données dans le cache et la base de données.

En général, l'utilisation du mécanisme de mise en cache peut améliorer considérablement les performances du programme et est particulièrement efficace lors du traitement de grandes quantités de données. Cette stratégie est également très pratique dans les systèmes à haute concurrence, et il est recommandé aux développeurs de l'essayer.

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:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn